1 / 23

Java Native Interface (JNI)

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

raisie
Download Presentation

Java Native Interface (JNI)

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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java Native Interface (JNI) Phil Pratt-Szeliga Syracuse University

  2. 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.

  3. 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){ doPrintString(str); } //the native keyword it present here private native void doPrintString(String str); }

  4. 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\

  5. 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" { #endif /* * 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 } #endif #endif

  6. 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

  7. 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;}

  8. 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“ FirstExample.cpp /DLL /OUT:first_example.dll /MACHINE:X64 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

  9. Load the .dll in Java package edu.syr.distobjects.jniexample; import java.io.File; 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”); System.load(file.getAbsolutePath()); } public void printString(String str){ doPrintString(str); } private native void doPrintString(String str); }

  10. 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); while(true){ byte[] buffer = new byte[32*1024]; intlen = is.read(buffer); if(len== -1) { break; } os.write(buffer, 0, len); } os.flush(); os.close(); is.close(); } }

  11. 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); }

  12. 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

  13. 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;

  14. JNI Field Functions • Based on Field Type: • GetObjectField • GetBooleanField • GetByteField • GetCharField • GetShortField • GetIntField • GetLongField • GetFloatField • GetDoubleField • Corresponding setters are like: • SetObjectField

  15. JNI Method Invocation Functions • Based on return type: • CallObjectMethod • CallBooleanMethod • CallByteMethod • CallCharMethod • CallShortMethod • CallIntMethod • CallLongMethod • CallFloatMethod • CallDoubleMethod • CallVoidMethod

  16. 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

  17. 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

  18. 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

  19. GPUs • 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

  20. Rootbeer • 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

  21. 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

  22. Questions?

  23. References http://dev.kanngard.net/Permalinks/ID_20050509144235.html http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html http://java.sun.com/docs/books/jni/html/jniTOC.html

More Related