NDK Integration (JNI) Lecture 5 Operating Systems Practical 11 November 2015 This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. OSP NDK Integration (JNI), Lecture 5 1/31 JNI Android JNI Example Native Method Arguments Mapping of Types Operations on Strings OSP NDK Integration (JNI), Lecture 5 2/31 Outline JNI Android JNI Example Native Method Arguments Mapping of Types Operations on Strings OSP NDK Integration (JNI), Lecture 5 3/31 JNI I Java Native Interface (JNI) I Native Programming Interface I Allows Java code to interoperate with apps and libraries written in other programming languages When do we use JNI? I I I I OSP Java library does not support platform-dependent features Use already existent library written in other language Time-critical code in a low level language (performance) NDK Integration (JNI), Lecture 5 4/31 JNI OSP I Two-way interface I Allows Java apps to invoke native code and vice versa NDK Integration (JNI), Lecture 5 5/31 Two-way Interface I I Support for two types of native code Native libraries I I I Native applications I I I OSP Call functions from native libraries In the same way they call Java methods Embed a Java VM implementation into native apps Execute components written in Java e.g. C web browser executes applets in an embedded Java VM implementation NDK Integration (JNI), Lecture 5 6/31 Implications of Using JNI I Java apps are portable I I I I Java is type-safe and secure I I I I I C/C++ are not Misbehaving native code can affect the whole application Security checks when invoking native code Extra care when writing apps that use JNI Native methods in few classes I OSP Run on multiple platforms The native component will not run on multiple platforms Recompile the native code for the new platform Clean isolation between native code and Java app NDK Integration (JNI), Lecture 5 7/31 Android NDK I Android Native Development Kit I I I ndk-build I I I I OSP Allows the embed C/C++ (native) code in Android applications Implement your own native code or use existing native libraries Shell script that invokes the NDK build scripts Probe the development system and app project file to decide what to build Generate binaries Copy binaries in the app’s project path NDK Integration (JNI), Lecture 5 8/31 Outline JNI Android JNI Example Native Method Arguments Mapping of Types Operations on Strings OSP NDK Integration (JNI), Lecture 5 9/31 Basic JNI Example - Android.mk I Android.mk I I I I I Configuration file In /jni The name of the native source file: hello-jni.c The name of the shared library to build: hello-jni Built library: libhello-jni.so LOCAL PATH := $ ( c a l l my−d i r ) i n c l u d e $ ( CLEAR VARS ) LOCAL MODULE := h e l l o − j n i LOCAL SRC FILES := h e l l o − j n i . c i n c l u d e $ ( BUILD SHARED LIBRARY ) OSP NDK Integration (JNI), Lecture 5 10/31 Basic JNI Example - Application.mk I Application.mk I I I In /jni Specifies the CPU and architecture for building In this example - all supported architectures APP ABI := a l l OSP NDK Integration (JNI), Lecture 5 11/31 Basic JNI Example - Java code I Java source code in /src I I I Load native library in a static initializer Declare the native function (native keyword) Call the native function package com . e x a m p l e . h e l l o j n i ; p u b l i c c l a s s H e l l o J n i extends A c t i v i t y { @Override p u b l i c void onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( savedInstanceState ) ; TextView t v = new TextView ( t h i s ) ; tv . setText ( stringFromJNI () ) ; setContentView ( tv ) ; } public native String stringFromJNI ( ) ; static { System . l o a d L i b r a r y ( ” h e l l o − j n i ” ) ; } } OSP NDK Integration (JNI), Lecture 5 12/31 Basic JNI Example - Native code I C source code in /jni I I I I Implements the native function Includes jni.h Function name - based on the Java function name and the path to the file containing it Arguments: I I I JNIEnv * - pointer to the VM, called interface pointer jobject - implicit this object passed from the Java side Creates a string by using a JNI function (NewStringUTF) #i n c l u d e < s t r i n g . h> #i n c l u d e < j n i . h> jstring J a v a c o m e x a m p l e h e l l o j n i H e l l o J n i s t r i n g F r o m J N I ( JNIEnv ∗ env , jobject thiz ) { r e t u r n ( ∗ e n v)−>NewStringUTF ( env , ” H e l l o from JNI ” ) ; } OSP NDK Integration (JNI), Lecture 5 13/31 Outline JNI Android JNI Example Native Method Arguments Mapping of Types Operations on Strings OSP NDK Integration (JNI), Lecture 5 14/31 JNIEnv interface pointer I I I I I OSP Passed into each native method call as the first argument Valid only in the current thread (cannot be used by other threads) Points to a location that contains a pointer to a function table Each entry in the table points to a JNI function Native methods access data structures in the Java VM through JNI functions NDK Integration (JNI), Lecture 5 15/31 JNIEnv interface pointer I I For C and C++ source files the syntax for calling JNI functions differs C code I I I JNIEnv is a pointer to a JNINativeInterface structure Pointer needs to be dereferenced first JNI functions do not know the current JNI environment I I I e.g. return (*env)->NewStringUTF(env, "Hello!"); C++ code I I I I OSP JNIEnv instance should be passed as the first argument to the function call JNIEnv is a C++ class JNI functions exposed as member functions JNI functions have access to the current JNI environment e.g. return env->NewStringUTF("Hello!"); NDK Integration (JNI), Lecture 5 16/31 Second Argument I Second argument depends whether the method is static or instance I Instance methods - can be called only on a class instance I Static methods - can be called directly from a static context I Both can be declared as native For instance native method I I I I For static native method I I OSP Reference to the object on which the method is invoked (this in C++) e.g. jobject thisObject Reference to the class in which the method is defined e.g. jclass thisClass NDK Integration (JNI), Lecture 5 17/31 Outline JNI Android JNI Example Native Method Arguments Mapping of Types Operations on Strings OSP NDK Integration (JNI), Lecture 5 18/31 Mapping of Types I I JNI defines a set of C/C++ types corresponding to Java types Java types I I OSP Primitive types: int, float, char Reference types: classes, instances, arrays I The two types are treated differently by JNI I int -> jint (32 bit integer) I float -> jfloat (32 bit floating point number) NDK Integration (JNI), Lecture 5 19/31 Primitive Types Java Type boolean byte char short int long float double OSP JNI Type jboolean jbyte jchar jshort jint jlong jfloat jdouble C/C++ Type unsigned char char unsigned short short int long long float double NDK Integration (JNI), Lecture 5 Size unsigned 8 bits signed 8 bits unsigned 16 bits signed 16 bits signed 32 bits signed 64 bits 32 bits 64 bits 20/31 Objects I Objects -> opaque references I C pointer to internal data structures in the Java VM Objects accessed using JNI functions (JNIEnv interface pointer) I I I All JNI references have type jobject I I I OSP e.g. GetStringUTFChars() function for accessing the contents of a string All reference types are subtypes of jobject Correspond to the most used types in Java jstring, jobjectArray, etc. NDK Integration (JNI), Lecture 5 21/31 Reference Types Java Type java.lang.Class java.lang. String java.lang.Throwable other objects java.lang.Object[] boolean[] byte[] char[] short[] int[] long[] float[] double[] other arrays OSP Native Type jclass jstring jthrowable jobject jobjectArray jbooleanArray jbyteArray jcharArray jshortArray jintArray jlongArray jfloatArray jdoubleArray jarray NDK Integration (JNI), Lecture 5 22/31 Outline JNI Android JNI Example Native Method Arguments Mapping of Types Operations on Strings OSP NDK Integration (JNI), Lecture 5 23/31 String Types I I String is a reference type in JNI (jstring) Cannot be used directly as native C strings I I I JNI supports UTF-8 and UTF-16/Unicode encoded strings I I I I I OSP Need to convert the Java string references into C strings and back No function to modify the contents of a Java string (immutable objects) UTF-8 compatible with 7-bit ASCII UTF-8 strings terminated with ’\0’ char UTF-16/Unicode Two sets of functions jstring is represented in Unicode in the VM NDK Integration (JNI), Lecture 5 24/31 Convert C String to Java String I NewStringUTF, NewString jstring javaString = env->NewStringUTF("Hello!"); I I Takes a C string, returns a Java string reference type If the VM cannot allocate memory I I I OSP Returns NULL OutOfMemoryError exception thrown in the VM Native code should not continue NDK Integration (JNI), Lecture 5 25/31 Convert Java String to C String I GetStringUTFChars, GetStringChars const jbyte* str = env->GetStringUTFChars(javaString, &isCopy); const jchar* str = env->GetStringChars(javaString, &isCopy); I isCopy I I I OSP JNI_TRUE - returned string is a copy of the chars in the original instance JNI_FALSE - returned string is a direct pointer to the original instance (pinned object in heap) Pass NULL if it’s not important I If the string contains only 7-bit ASCII chars you can use printf I If the memory allocation fails it returns NULL, throws OutOfMemory exception NDK Integration (JNI), Lecture 5 26/31 Release Strings I Free memory occupied by the C string I ReleaseStringUTFChars, ReleaseStringChars env->ReleaseStringUTFChars(javaString, str); OSP I String should be released after it is used I Avoid memory leaks I Frees the copy or unpins the instance (copy or not) NDK Integration (JNI), Lecture 5 27/31 Length and Copy in Buffer I Get string length I I I GetStringUTFLength/GetStringLength on the jstring Or strlen on the GetStringUTFChars result Copy string elements into a preallocated buffer env->GetStringUTFRegion(javaString, 0, len, buffer); I I I I OSP start index and length length can be obtained with GetStringLength buffer is char[] No memory allocation, no out-of-memory checks NDK Integration (JNI), Lecture 5 28/31 Critical Region I GetStringCritical, ReleaseStringCritical I Increase the probability to obtain a direct pointer to the string Critical Section between the calls I I I I I I OSP Must not make blocking operations Must not allocate new objects in the Java VM Disable garbage collection when holding a direct pointer to a string Blocking operations or allocating objects may lead to deadlock No GetStringUTFCritical -> usually makes a copy of the string NDK Integration (JNI), Lecture 5 29/31 Bibliography OSP I http://www.soi.city.ac.uk/~kloukin/IN2P3/ material/jni.pdf I http://docs.oracle.com/javase/6/docs/technotes/ guides/jni/spec/jniTOC.html I http://download.java.net/jdk8/docs/technotes/ guides/jni/spec/functions.html I http://developer.android.com/training/articles/ perf-jni.html I Onur Cinar, Pro Android C++ with the NDK, Chapter 3 I Sylvain Ratabouil, Android NDK, Beginner’s Guide, Chapter 3 NDK Integration (JNI), Lecture 5 30/31 Keywords Java Native Interface I Primitive types I Two-way interface I Reference types I Native methods I JNI functions I Interface pointer I Opaque reference I Static methods I Java string reference I Instance methods I Conversion operations I OSP NDK Integration (JNI), Lecture 5 31/31