Originally posted on: http://geekswithblogs.net/JoshReuben/archive/2015/02/16/jni--the-java-native-interface.aspx
*note:
for brevity, error checking code has been left out of this post.
Overview
The
JNI API allows
Java applications to invoke native C/C++
code and native C/C++
code to invoke
Java.
Using
the JNI comes at the cost of losing JIT
portability &
type safety – recompilation of
native code is machine instruction-set specific.
Usage
Declare a Native Method in
Java:
}
Use
javac
to compile the
Java class from the MyClass.java
source file:
javac
MyClass.java
use
javah
to generate a JNI header file - generate a
MyClass.h
file of same name
containing the function prototype for the native method
implementation:
The
JNI
header file will
appear in the following format:
JNIEXPORT
macro - export
function from native library
JNICALL
macro - cause C
compiler to generate
code correct calling convention for this function.
The
generated name
of the C function is formed by concatenating the “Java_”
prefix, the class name, and the method name.
1st
argument - JNIEnv
- interface pointer to
a pointer to a function table.
2nd
argument - jobject
or jclass
- a reference to
the java object
instance on which the native
method is defined. If defined as static
native, is a
reference to the class.
Write
the Native Method Implementation. Compile the
C/C++
implementation into a .so
native library
Run
the Program - specify the native library path to
the local directory on the java
command line – D
switch sets a Java platform system
property. (alternatively set
the LD_LIBRARY_PATH
environment variable).
Type Mappings and Member
Descriptor Strings
The
JNI defines a set of C / C++ types that correspond to types in Java –
for primitive
types (eg jfloat,
jstring) /
reference types (classes,
instances, arrays – all of which have
type jobject).
native
code can
manipulate java objects
via JNI functions exposed
through the JNIEnv
interface pointer.
Eg
a canonical native method with String
params and retval
.java
file:
.h
file:
JNIEXPORT
jstring
JNICALL Java_MyClass_doSomething(JNIEnv
*env, jobject this, jstring
s);
JNI
member descriptor
C strings –
specify a type.
Primitive types have specific descriptors
eg I for int
, Z for Boolean,
F for float, D for double. For a reference
type the descriptor begins
with the letter L,
is followed by the JNI class descriptor, and ends
with a semicolon. The dot
separators in FQ
class names are changed to slashes
in JNI class descriptors. Eg
java.lang.String ? "Ljava/lang/String;"
Descriptors
for array types start
with
“[”
,
followed by the descriptor of the array
element
type eg
float[]
? "[f"
javap
-s
-p - generate &
print field descriptors from class files:
javap
-s -p myClassMember
-->
method
descriptors -
argument types appear first, are listed in
order with no separators,
and are surrounded by brackets.
A method that
takes no arguments is represented with an
empty bracket pair.
Eg, "(F)V"
- denotes a method that takes one argument of type float
and has return type void.
"()F"
denotes a method that takes no arguments and returns a float.
Method
descriptors may contain class descriptors.
Descriptors
for array types begin with the “[”
character, followed by the descriptor of
the array element type. Eg
Passing String Params
JNI
String Functions:
}
Passing Array Params
JNIprimative
arrays are represented by j<T>array
types eg
jintArray.
use JNI functions to access primitive array elements
JNI Primitive Array Functions
JNI
Object Arrays
- separate
pair of functions – Get/SetObjectArrayElement
- access
arrays of strings or
multi-d arrays.
note:
a multidimensional
jagged array of
primitives is
considered
an object array.
Eg
a static
native
method to create a 2D
int
array
java:
static native int[][] doSomething(int size1, int size2);
...
int[][] aa = initInt2DArray(4,4);
c:
JNIEXPORT jobjectArray JNICALL Java_MyClass_doSomething(
JNIEnv *env, jclass cls, int size1, int size2) {
jclass intArrCls = (*env)->FindClass(env, "[I"); // "[I" argument - JNI class descriptor for Java int[] type
// allocate the 1st dimension of an array of element type specified by the jclass reference
jobjectArray aa = (*env)->NewObjectArray(env, size1, intArrCls, NULL);
for (int i = 0; i < size1; i++) {
jint buff[size2]; // make sure it is large enough
<span style="background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; backgr