420 likes | 563 Vues
This comprehensive guide explores the Java Native Interface (JNI), a key feature for enabling Java applications to interact with native code in languages such as C and C++. Understand the rationale behind using Foreign Function Interfaces (FFIs), the benefits of JNI, and its performance implications. Learn about JNI’s design principles, integration steps from Java to C, as well as best practices and potential pitfalls. This resource is essential for developers looking to optimize Java applications with native libraries or perform time-critical tasks in lower-level languages.
E N D
Foreign Function Interface More Specifically JNI Justin Catterson
Most languages have a foreign function interface • ADA • C++ • Java • Ruby • Python • Haskell • Perl • etc. What is a Foreign Function Interface? Simply an interface which allows languages to interact with one another
Reasons for needing Foreign Function Interfaces • Reuse of Legacy Code • Add libraries to language (Object Oriented) • Performance
JNI (Java Native Interface) Released in 1997 Used to call native methods Used to embed a Java Virtual Machine into native applications Suns JDK 1.4.2 contains over 600,00 lines of native C code
Issues with JNI • Software Security • Loss of Portability • Mapping is not easy • Only supports C/C++ can do Ada, Fortran, COBOL but it is more difficult • Strong knowledge in both Java and C • Overhead?
When should I use JNI? When to use • Java API doesn’t support certain features required by application • Want to access an existing library • Implement time-critical sections in a low level language • Multiple processes are taking up too much memory When NOT to use • When you could communicate with native language through TCP/IP connection • Could connect to database using JDBC • Distributed object technology such as Java IDL API
Goals of JNI • Binary Compatibility • Little overhead • Native methods full use of JVM • Not the only FFI available for Java
Design Principles • Make control flow as simplistic as possible • Keep native code minimal (Error checking) • Isolate native code (“Porting layer”)
Basic steps Java to Cthrough command prompt • Add to the system variable path the location of your JDK bin (ie. C:\Program Files (x86)\Java\jdk1.6.0_20\bin) • Write java class with at least one method declared native (ie. Public native void hello() ) • Add call to System.loadLibrary (ie. Static { System.loadLibrary(“hello”);} • Compile java code using javac
Basic steps Java to Cthrough command prompt Create header file for the c using javah Write native method for hello with microsoft visual studio, execute the vcvarsall.bat in the vc directory of visual studio Compile native file into a dll (using cl -Iinclude -Iinclude\win32 -MD -LD hello.cpp -Fejnihello.dll) –l is where the include and include\win32 directories are from the jdk Run the java program
Run example jni
Extra Parameters? • JNIEnv pointer contains the location of the function table • If method is (java static), the method belongs to the java class that contains the native function
How do we use an existing native library? One-to-one mapping public class C { public static native intatol(String str); } JNIExportjint JNICALL Java_C_atol(JNIEnv *env, jclasscls, jstringstr) { const char *cstr = env->GetStringUTFChars(str, 0); if (cstr == NULL) { return 0; // out of memory } int result = atol(cstr); env->ReleaseStringUTFChars(str, cstr); return result; }
C++ to Java (Embed JVM into C++) • Write the Java code • Compile java • Write C++ • Compile C++ • run the exe (Ensure you have the JVM dll directory in the system variable path)
Run example cToJava
JNI functions • http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html
JNI and Performance • Typically accepted C and C++ is faster than Java • Is it expensive to make the call through JNI?
Experiment Run benchmark tests to measure execution time between two algorithms in Java and C++ • HeapSort ( Memory ) • Discrete Fast Fourier Transform ( Heavy Math)
Discrete Fast Fourier Transform • Check java’s performance for mathematical computations • If you are interested in learning more • http://home.comcast.net/~szemengtan/LinearSystems/fft.pdf
HeapSort • Array sizes of 250, 1000, and 10000. To check the impact of array sizes on Java and JNI • Vary number of iterations to check start-up cost
Not expensive enough to not use Still has cost associated pending the JIT 800-1350 ns per call + 25 to 30ns for each argument (DawidKurzyniec and VaidySunderam)
How to handle overhead cost? • JVM memory and native memory space transfer (hash map store recently accessed fieldids and methods) • Arrays primary concern ( Try to avoid passing them) • Pending VM may make copy
Types • Primitive • Reference
Reference Types (opaque refrences) All JNI objects inherit from jObject Treated as pointers
Opaque References • Local • Global • Weak
Local References • Content that is created from a native method will only exist during the execution of the native method. Memory corruptions Or system crashes Attempted to use invalid Local address jstring MyNewString(JNIEnv *env, jchar *chars, jintlen) { static jclassstringClass = NULL; jmethodID cid; jcharArrayelemArr; jstring result; if (stringClass == NULL) { stringClass = (*env)->FindClass(env, "java/lang/String"); if (stringClass == NULL) { return NULL; /* exception thrown */ }} /* It is wrong to use the cached stringClass here, because it may be invalid. */ cid = (*env)->GetMethodID(env, stringClass, "<init>", "([C)V"); ... elemArr = (*env)->NewCharArray(env, len); ... result = (*env)->NewObject(env, stringClass, cid, elemArr); (*env)->DeleteLocalRef(env, elemArr); return result; }
Global References • Exists until the programmer deletes the object • No GC jstring MyNewString(JNIEnv *env, jchar *chars, jintlen) { static jclassstringClass = NULL; ... if (stringClass == NULL) { jclasslocalRefCls = (*env)->FindClass(env, "java/lang/String"); if (localRefCls == NULL) { return NULL; /* exception thrown */ } /* Create a global reference */ stringClass = (*env)->NewGlobalRef(env, localRefCls); /* The local reference is no longer useful */ (*env)->DeleteLocalRef(env, localRefCls); /* Is the global reference created successfully? */ if (stringClass == NULL) { return NULL; /* out of memory exception thrown */ } } ... } NewGlobalRef
Weak References JNIEXPORT void JNICALL Java_mypkg_MyCls_f(JNIEnv *env, jobject self) { static jclass myCls2 = NULL; if (myCls2 == NULL) { jclass myCls2Local = (*env)->FindClass(env, "mypkg/MyCls2"); if (myCls2Local == NULL) { return; /* can’t find class */ } myCls2 = NewWeakGlobalRef(env, myCls2Local); if (myCls2 == NULL) { return; /* out of memory */ } } ... /* use myCls2 */ } • Similar to Global references • Valid across native methods and threads • Don’t care if object gets GC
Threading and JNI • JNIenv pointer cannot cache must pass pointer associated with the specific thread • Local references valid only for thread that created it, pass global references • Synchronization use MoniterEnter/MoniterExit
Problems • Safety Guarantees • Safe Language + Unsafe Language = unsafe • C code is unsafe, you may read/write to any memory address • C code can pass objects of wrong type back to Java and therefore violate Java's type checks • Memory Mangement ( calls to release)
How Read/Write problems occur • Private? Constants? • From references, C can see private data and change the values of constants • Interface pointers, this is how C can use Java’s functions. C can overwrite the entries in the function table. • Array Index out of bounds, accidently read/write directly to Java’s heap
Solution? • Safe interoperation (Remote Prodecure Calls) • Ccured (pointer arithmetic solutions) • SafeJNI (wrap JNI api calls) • Jeannie
Remote Procedure Calls • Place components in different address space • Significant overhead
Ccured • Internal safety for C code • Separates pointers by usage • Helps remove array index out of bounds errors
Applications • Real-Time Embedded • Use Java for upper levels (UI, threading, networking) • Have C++/C interface with hardware and signaling, support already exists
Android NDK C • Hardware sensors • Platform operations • 3D libraries Android (JavaME) -- Linux
Conclusions • Use JNI to expand language libraries/ use legacy programs • JNI useful for embedded systems • Java can be easily abused using JNI • Keep native methods in the same “package”
References • 1] Sheng Liang (June 1999). The Java Native Interface Programmer’s Guide and Specification. Retrieved from http://java.sun.com/docs/books/jni/download/jni.pdf • [2] Gang Tan; Andrew W. Appel; SrimatChakradhar; AnandRaghunathan; Srivaths Ravi; Daniel Wang (2006). Safe Java Native Interface.Retrieved from http://www.cs.princeton.edu/~appel/papers/safejni.pdf • [3] Scott Stricker(March 2002). Java Programming with JNI. • Retrieved from http://www.ibm.com/developerworks/java/tutorials/j-jni/ • [4] DawidKurzyniec; VaidySunderam. Efficient Cooperation between Java and Native • Codes - JNI Performance Benchmark. • Retrieved from http://janet-project.sourceforge.net/papers/jnibench.pdf • [5] Demetrius L. Davis. To JNI or not to JNI? • Retrieved from http://www.ewp.rpi.edu/hartford/~rhb/cs_seminar_2004/SessionC3/davis.pdf • [6] PreethamChandrian (August 2011). Efficient Java Native Interface for Android based Mobile Devices. • Retrieved from http://repository.asu.edu/items/9315