Java native interface jni
1 / 23

Java Native Interface (JNI) - PowerPoint PPT Presentation

  • Uploaded on

Java Native Interface (JNI). Phil Pratt-Szeliga Syracuse University. JNI Overview. JNI allows a developer to interop with arbitrary C/C++ code The managed to native transition can take time, so don’t expect a performance enhancement from, say, repeatedly incrementing an integer

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
Download Presentation

PowerPoint Slideshow about ' Java Native Interface (JNI)' - raisie

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Java native interface jni

Java Native Interface (JNI)

Phil Pratt-Szeliga

Syracuse University

Jni overview
JNI Overview

  • JNI allows a developer to interop with arbitrary C/C++ code

  • The managed to native transition can take time, so don’t expect a performance enhancement from, say, repeatedly incrementing an integer

  • With JNI you need to have a .dll built for Windows and a .so built for Linux (and I guess a .so for Mac).

    • Your build process needs to be able to built the .dllon Windows and the .so on Linux and then possibly pack it in the jar file

    • You need to build two separate dll’s and so’s to cover 32bit and 64bit platforms.

Calling jni code from java
Calling JNI Code From Java

package edu.syr.distobjects.jniexample;

public class FirstExample{

//it is good to make public wrappers around

//native methods

public void printString(String str){



//the native keyword it present here

private native void doPrintString(String str);


Creating the c c headers
Creating the C/C++ Headers

  • Directory structure:

    • netbeans_root

      • build

        • classes

          • edu

            • syr

              • distobjects

                • jniexample

      • src

        • edu

          • syr

            • distobjects

              • jniexample

    • native (you need to make this directory)

  • Linux:

    • $ cd /path/to/netbeans_root/build/classes

    • $ javahedu.syr.distobjects.jniexample.FirstExample

    • $ mv edu_syr_distobjects_jniexample_FirstExample.h../../native/

  • Windows:

    • $ cd \path\to\netbeans_root\build\classes

    • $ “C:\Program Files (x86)\Java\jkd1.6.0_26\bin\javah”edu.syr.distobjects.jniexample.FirstExample

    • $ move edu_syr_distobjects_jniexample_FirstExample.h..\..\native\

  • Created c c header
    Created C/C++ Header

    /* DO NOT EDIT THIS FILE - it is machine generated */

    #include <jni.h>

    /* Header for class edu_syr_distobjects_jniexample_FirstExample */

    #ifndef _Included_edu_syr_distobjects_jniexample_FirstExample

    #define _Included_edu_syr_distobjects_jniexample_FirstExample

    #ifdef __cplusplus

    extern "C" {



    * Class: edu_syr_distobjects_jniexample_FirstExample

    * Method: doPrintString

    * Signature: (Ljava/lang/String;)V


    JNIEXPORT void JNICALL Java_edu_syr_distobjects_jniexample_FirstExample_doPrintString

    (JNIEnv *, jobject, jstring);

    #ifdef __cplusplus




    Copy prototype to cpp file
    Copy Prototype to .cpp File

    #include “edu_syr_distobjects_jniexample_FirstExample.h”

    JNIEXPORT void JNICALL Java_edu_syr_distobjects_jniexample_FirstExample_doPrintString

    (JNIEnv* env, jobjectthis_obj, jstringstr)


    Note I gave names to env, this_obj, and str.

    env: Every JNI function is passed a JNIEnv pointer

    this_obj: Represents the managed “this” pointer

    str: The only argument to the method in the Java code

    Implement a cout
    Implement a cout

    #include “edu_syr_distobjects_jniexample_FirstExample.h”

    #include <iostream>

    JNIEXPORT void JNICALL Java_edu_syr_distobjects_jniexample_FirstExample_doPrintString

    (JNIEnv * env, jobjectthis_obj, jstringstr)


    intlen = (*env)->GetStringLength(env, str);

    char * nstr = new char[len];

    (*env)->GetStringUTFRegion(env, str, 0, len, nstr);

    std::cout << nstr << std::endl;

    delete [] nstr;}

    Build the dll
    Build the .dll

    Put this in cl_options.txt (on one line)

    /I"C:\Program Files\Java\jdk1.6.0_26\include“

    /I"C:\Program Files\Java\jdk1.6.0_26\include\win32“





    Make a native_build.bat (keep lines separate)

    "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64

    cl @cl_options.txt

    Load the dll in java
    Load the .dll in Java

    package edu.syr.distobjects.jniexample;


    public class FirstExample {

    //called during first initialization of FirstExampleclass

    static {

    //load requires an absolute path and this method ensures that File file = new File(“first_example.dll”);



    public void printString(String str){



    private native void doPrintString(String str);


    Distributing the dll with a jar
    Distributing the .dll with a .jar

    In netbeans if you create a package (folder) and then have your build process place the .dll in the folder, it will be included in the .jar

    public class BinaryLoader {

    public void extractBinary(String filename) throws Exception {

    String path = "/edu/syr/distobjects/jniexample/native/"+filename;

    InputStreamis = BinaryLoader.class.getResourceAsStream(path);

    OutputStreamos = new FileOutputStream(filename);


    byte[] buffer = new byte[32*1024];

    intlen =;

    if(len== -1) { break; }

    os.write(buffer, 0, len);


    os.flush(); os.close(); is.close();



    Saving state in a cpp
    Saving State In a cpp

    • You can save state in a high performance way by using static globals in a cpp

      • But all instances of a class will share that state

    • A slower way is to save state back to a Java Field

      void setLongField(JNIEnv * env, jobjectobj, long value){

      jclassthis_class = (*env)->GetObjectClass(env, obj);

      jfieldIDfid = (*env)->GetFieldID(env, this_class, “m_FieldName”, "J");

      (*env)->SetLongField(env, obj, fid, value);


    Java type strings
    Java Type Strings

    • Previously we passed in “J” into GetFieldID

      • B = byte

      • C = char

      • D = double

      • F = float

      • I = int

      • J = long

      • S = short

      • V = void

      • Z = boolean

      • Ljava/lang/String; = String

      • Ljava/lang/Object; = Object

      • Lfully/qualified/Classname = fully.qualified.Classsname

      • [B – single dimensional byte array

      • [[B – two dimensional byte array

      • [Ljava/lang/String; - one dimensional string array

    Calling a java method
    Calling a Java Method

    jbyteArraylist_get(JNIEnv* env, jobjectlist, int index){

    jmethodID mid;

    jclasslist_interface = (*env)->FindClass(env, "java/util/List");

    mid = (*env)->GetMethodID(env, list_interface, "get", "(I)Ljava/lang/Object;");

    return (*env)->CallObjectMethod(env, list, mid, index);


    • “java/util/List” – interface or class name

    • “get” – method name

    • “(I)Ljava/lang/Object;” – a method that accepts an int as a parameter and returns a Ljava/lang/Object;

    • jbyteArray – a byte[]

    • In Java, the list was declared as:

      • List<byte[]> list;

    Jni field functions
    JNI Field Functions

    • Based on Field Type:

      • GetObjectField

      • GetBooleanField

      • GetByteField

      • GetCharField

      • GetShortField

      • GetIntField

      • GetLongField

      • GetFloatField

      • GetDoubleField

    • Corresponding setters are like:

      • SetObjectField

    Jni method invocation functions
    JNI Method Invocation Functions

    • Based on return type:

      • CallObjectMethod

      • CallBooleanMethod

      • CallByteMethod

      • CallCharMethod

      • CallShortMethod

      • CallIntMethod

      • CallLongMethod

      • CallFloatMethod

      • CallDoubleMethod

      • CallVoidMethod

    Jni array functions
    JNI Array Functions

    • Based on Array Type:

      • GetBooleanArrayElements

      • GetByteArrayElements

      • GetCharArrayElements

      • GetShortArrayElements

      • GetIntArrayElements

      • GetLongArrayElements

      • GetFloatArrayElements

      • GetDoubleArrayElements

    • Corresponding releases need to be called like:

      • ReleaseBooleanArrayElements

    • Array length:

      • GetArrayLength

    • Arrays of objects: can only get one at a time because you can’t know the size of an object to store in a regular C style array

      • GetObjectArrayElement

      • SetObjectArrayElement

    Example of jni array copy
    Example of JNI Array Copy

    JNIEXPORT void JNICALL Java_edu_syr_pcpratts_rootbeer_ArrayMemory_doWriteIntArray

    (JNIEnv *env, jobjectthis_obj, jintArray array, jlong ref, jintlen){

    char * dest = (char *) ref;

    jint* narray = (*env)->GetIntArrayElements(env, array, JNI_FALSE);

    memcpy(dest, narray, len*sizeof(int));

    (*env)->ReleaseIntArrayElements(env, array, narray, JNI_ABORT);


    jlong ref was previously allocated in the C++ code using new. You can easily save any pointer in C++ in a Java field using a long. ref was saved as a member field in the Java class.

    JNI_FALSE and JNI_ABORT have to deal with memory pinning and copying back of the change array into the java runtime. I can’t find a reference right now for these

    Real world usage of jni
    Real World Usage of JNI

    • Rootbeer: tool to make it easier to program GPUs from Java

      • All the GPU vendors give C bindings to their API.

      • API allows to:

        • Create/Destroy GPU memory

        • Copy from CPU memory to GPU memory

        • Query how many sub-processors a GPU has

        • Compile CUDA programs to a binary for the GPU

        • Launch jobs onto the GPU


    • GPU = Graphics Processing Unit

      • Specialized processor originally made only to feed Monitor with byte buffer

      • A device has on the order of 512 cores!

      • Each core is quite simple and slow:

        • No branch prediction or out of order execution

        • Clock rate is 1.3 Ghz range

      • Groups of 32 cores all have to be doing the same thing

        • They share instruction fetch hardware

      • Really hard to program

        • Need to learn special programming language to execute on the GPU (CUDA)

        • Need to manually serialize all of your complex classes in C/C++ to arrays (this may have changed recently…need to check)

        • Need to find huge amounts of parallelism in original program to get a speedup

          • Getting a speedup is the only reason to use a GPU

          • Naïve Dense matrix multiplication can easily be sped up 100X


    • Rootbeer allows the developer to program in Java and it automatically:

      • Creates a CUDA program from analyzing Java Bytecode (with the help of the Soot Java Optimization Framework)

      • Creates Java Bytecode that can (de)serialize CPU memory to GPU memory in a high performance manner

      • Gives a Java interface for automatically launching these jobs on the GPU

    Rootbeer status
    Rootbeer Status

    • By the end of summer 2012 there will be a public release of Rootbeer available for people to use

      • We currently have a non-optimized version that is highly tested:

        • 20K SLOC product code

        • 5k SLOC test code

        • All tests pass covering all aspects of the Java programming language except:

          • Sleeping while inside a monitor

          • Reflection

          • Dynamic methods in Java (recently added to Java, makes static analysis really hard)

          • Java Code that uses JNI…

          • Garbage collection