Post on 17-Dec-2015
FOREIGN FUNCTION INTERFACEMore 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 1997Used 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
1. Add to the system variable path the location of your JDK bin (ie. C:\Program Files (x86)\Java\jdk1.6.0_20\bin)
2. Write java class with at least one method declared native (ie. Public native void hello() )
3. Add call to System.loadLibrary (ie. Static { System.loadLibrary(“hello”);}
4. Compile java code using javac
BASIC STEPS JAVA TO CTHROUGH COMMAND PROMPT
5. Create header file for the c using javah6. Write native method for hello7. with microsoft visual studio, execute the
vcvarsall.bat in the vc directory of visual studio
8. 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
9. Run the java program
RUN EXAMPLE
jni
Extra Parameters?
1. JNIEnv pointer contains the location of the function table
2. 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 int atol(String str);
}
JNIExport jint JNICALLJava_C_atol(JNIEnv *env, jclass cls, jstring str){
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++)
1. Write the Java code2. Compile java3. Write C++4. Compile C++5. 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++
1. HeapSort ( Memory )2. 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/Li
nearSystems/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
Results
Why the performance hit at size 10,000 for JNI?
Not expensive enough to not useStill has cost associated pending the JIT800-1350 ns per call + 25 to 30ns for each argument (Dawid Kurzyniec and Vaidy Sunderam)
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
Types1. Primitive
2. Reference
Primitive Types
Java Language Type Native Type Description
boolean jboolean Unsigned 8 bits
byte jbyte Signed 8 bits
Char jchar Unsigned 16 bits
short jshort Signed 16bits
int jint Signed 32 bits
long jlong Signed 64 bits
float jfloat 32 bits
double jdouble 64 bits
Reference Types (opaque refrences)
All JNI objects inherit from jObject
Treated as pointers
Opaque References
1. Local 2. Global3. Weak
Local References
Content that is created from a native method will only exist during the execution of the native method.
Memory corruptionsOr system crashesAttempted to use invalidLocal address
jstring MyNewString(JNIEnv *env, jchar *chars, jint len) { static jclass stringClass = NULL; jmethodID cid; jcharArray elemArr; 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
jstringMyNewString(JNIEnv *env, jchar *chars, jint len){static jclass stringClass = NULL;...if (stringClass == NULL) {jclass localRefCls =(*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 Similar to Global references
Valid across native methods and threads
Don’t care if object gets GC
JNIEXPORT void JNICALLJava_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 */}
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; Srimat Chakradhar; Anand Raghunathan; 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] Dawid Kurzyniec; Vaidy Sunderam. 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] Preetham Chandrian (August 2011). Efficient Java Native Interface for Android based
Mobile Devices. Retrieved from http://repository.asu.edu/items/9315