The document discusses the Java Native Interface (JNI) which allows Java code running in the Java Virtual Machine to call and be called by native code such as C and C++. It covers when JNI is useful, how to define native methods in Java classes, implement them in other languages, and interact with Java objects from native code including calling methods and accessing fields and arrays. It also discusses handling exceptions and local vs global references when working with JNI.
Getting Started with the Java Native Interface (JNI
1. Fullstack as a service
Getting Started with the JNI
Java Native Interface
Kirill Kounik
2. - I am part of 12+ people strong Tikal's Android
group.
- Experience in startup and medium sized
companies
- 6.5 years in Sun Microsystems with JME
technology
- Java, client, low level
- Graduate of Technion in Computer Science
WHO AM I?
3. Agenda
What JNI can do
Simple example
JNI basics
Native JNI functions
Java type mapping
Inspecting classes, calling Java methods
Processing Exceptions
5. When JNI is useful - Pros
The standard Java class library does not support the platform-dependent
features needed by the application.
You already have a library written in another language, and wish to make it
accessible to Java code through the JNI.
You want to implement a small portion of time-critical code in a lower-level
language.
6. When JNI is useful - Cons
You program is not platform independent anymore
You are using low level language with all its drawbacks
JNI call costs time http://stackoverflow.com/questions/13973035/what-is-the-
quantitative-overhead-of-making-a-jni-call
java version "1.7.0_09"
OpenJDK Runtime Environment (IcedTea7 2.3.3) (7u9-2.3.3-1)
OpenJDK Server VM (build 23.2-b09, mixed mode)
Linux visor 3.2.0-4-686-pae #1 SMP Debian 3.2.32-1 i686 GNU/Linux
7. JNI access to JVM
Native JNI code leaves side by side with the JVM and has access to its structures.
Create, inspect, and update Java objects (including arrays and strings).
Call Java methods.
Catch and throw exceptions.
Load classes and obtain class information.
Perform runtime type checking.
Create threads visible to JVM
8. Native method in Java class
package jni;
public class CHelloWorld {
native String hello();
static {
System.loadLibrary("jni_CHello");
}
public static void main(String[] args) {
CHelloWorld chw = new CHelloWorld();
System.out.println(chw.hello());
}
}
13. Resolving method names
A native method name is concatenated from the following components:
• the prefix Java_
• a mangled fully-qualified class name
• an underscore (“_”) separator
• a mangled method name
• for overloaded native methods, two underscores (“__”) followed by the
mangled argument signature
14. javah tool
The javah command conveniently generates C header and source files that are
needed to implement native methods. (Generated files not really required)
$ javah -d .srcnative -cp .binjava jni.CHelloWorld
15. JNI native function arguments
The JNI interface pointer is the first argument to native methods. The JNI
interface pointer is of type JNIEnv.
The second argument differs depending on whether the native method is static
or nonstatic.
• The second argument to a nonstatic native method is a reference to the object.
• The second argument to a static native method is a reference to its Java class.
16. JNI native function arguments
The remaining arguments correspond to regular Java method arguments.
The native method call passes its result back to the calling routine via the return
value
17. JNIEvn*
Reference to JNI environment, which lets you access all the JNI functions. Used
for:
Create new objects
Access Fields inside Java classes
Invoke Java Methods.
It points to the thread’s local data, so it cannot be shared between threads.
18. Note on C++
#include <jni.h>
extern ”C” {
jstring Java_jni_CHelloWorld_hello(JNIEnv *env, jobject thiz)
{
return env->NewStringUTF("hello, world (from JNI)");
}
}
19. Arguments of a primitive type passed by value
Java Type Native Type Constants
boolean jboolean JNI_FALSE, JNI_TRUE
byte jbyte
char jchar
short jshort
int jint
long jlong
float jfloat
double jdouble
void void
jsize scalar values and sizes
22. Local and Global References
• Every argument passed to JNI call is a local reference that is valid only for the
duration of the call. This applies to all sub-classes of jobject, including
jclass, jstring, and jarray.
• In order to get Global references:
jobject NewGlobalRef(JNIEnv *env, jobject obj);
• Global reference is live until it is not explicitly released
void DeleteGlobalRef(JNIEnv *env, jobject globalRef);
23. Local and Global References
• Do "not excessively allocate" local references.
• Free local references them manually with DeleteLocalRef()
• The implementation is only required to reserve slots for 16 local references,
• if you need more than that you should either delete as you go or use
EnsureLocalCapacity/PushLocalFrame to reserve more
24. Passing array arguments
/* private native long sumAll(int[] numbers); */
jlong Java_jni_CHelloWorld_sumAll(JNIEnv *env, jobject thiz, jintArray
values_) {
jint *values = (*env)->GetIntArrayElements(env, values_, NULL);
jsize len = (*env)->GetArrayLength(env, values_);
jlong sum = 0;
int i;
for (i = 0; i < len; i++) {
sum += values[i];
}
(*env)->ReleaseIntArrayElements(env, values_, values, 0);
return sum;
}
25. On class file structure
Goal: read or write class or instance variables from the JNI code
Goal: call java methods from the JNI code
Java VM type signatures:
Z boolean
B byte
C char
S short
I int
J long
F float
D double
Lfully-qualified-class; fully-qualified-class
[type type[]
(arg-types)ret-type method type
26. VM Signature example
Example Java method signature
long foo(int n, String s, int[] arr);
JVM Type signature:
(ILjava/lang/String;[I)J
27.
28. javap tool
javap is Java Class File disassembler tool that comes to rescue
$ javap -s -p -cp .binjava jni.CHelloWorld
29. Accessing class/instance members
Find correct class object
Find member index, either method or field
Use correct instance object
Do method invocation or field access
30. Non-static method invocation
- Find class of your object
jclass cl = (*env)->GetObjectClass(env, textView);
- Find method
jmethodID methodId = (*env)->GetMethodID(env, cl, "setText", "(Ljava/lang/CharSequence;)V");
- Call your method using correct JNI function
(*env)->CallVoidMethod(env, textView, methodId, … );
32. Accessing instance fields
- Find object’s class
- Get field id
jfieldID fieldId = (*env)->GetFieldID(env, clazz, "chars", "[C");
- Get/set field value using correct method
jobject o = (*env)->GetObjectField(env, instance, jfieldID );
(*env)->SetObjectField(env, instance, jfieldId, /* NativeType */ value);
33. Accessing static fields
- Find correct class if needed
- Find static field
jfieldID fieldId = (*env)->GetStaticFieldID(env, clazz, "count", "I");
- Get/set static field value using correct method
jint i = (*env)->GetStaticIntField(env, instance, jfieldID );
(*env)->SetStaticIntField(env, instance, jfieldId, /* NativeType */ 5);
34. Checking for errors
Calling most of JNI functions is not allowed if exception is pending and will cause
crash. When there is a chance on an exception JNI must check for the exception
state
jboolean ExceptionCheck(JNIEnv *env);
jthrowable ExceptionOccurred(JNIEnv *env);
void ExceptionClear(JNIEnv *env);
void ExceptionDescribe(JNIEnv *env);