getting started with the jni

36
Fullstack as a service Getting Started with the JNI Java Native Interface Kirill Kounik

Upload: kirill-kounik

Post on 14-Apr-2017

159 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Getting started with the JNI

Fullstack as a service

Getting Started with the JNIJava Native Interface

Kirill Kounik

Page 2: Getting started with the JNI

- 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?

Page 3: Getting started with the JNI

Agenda

What JNI can doSimple exampleJNI basics

Native JNI functionsJava type mappingInspecting classes, calling Java methodsProcessing Exceptions

Page 4: Getting started with the JNI

Goal

Page 5: Getting started with the JNI

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.

Page 6: Getting started with the JNI

When JNI is useful - Cons

You program is not platform independent anymoreYou are using low level language with all its drawbacksJNI call costs time http://stackoverflow.com/questions/13973035/what-is-the-

quantitative-overhead-of-making-a-jni-calljava 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

Page 7: Getting started with the JNI

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

Page 8: Getting started with the JNI

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());}

}

Page 9: Getting started with the JNI

Native method implementation

#include <jni.h>

/** Class: jni_CHelloWorld* Method: hello* Signature: ()Ljava/lang/String;*/

jstring Java_jni_CHelloWorld_hello(JNIEnv *env, jobject thiz)

{

return (*env)->NewStringUTF(env, "hello, world (from JNI)");

}

Page 10: Getting started with the JNI

Native method implementation

jstring ← Java return type

Java_jni_CHelloWorld_hello( JNIEnv* env, jobject thiz )

Naming convention for JNI functions “this” object

reference

Pointer to JNI environment for JNI functions access

Page 11: Getting started with the JNI

Method overloading

package jni;

public class CHelloWorld {

native String hello();native String hello(String what, int count);

. . .}

Page 12: Getting started with the JNI

Method overloading/** Class: jni_CHelloWorld* Method: hello* Signature: ()Ljava/lang/String;*/

JNIEXPORT jstring JNICALL Java_jni_CHelloWorld_hello__ (JNIEnv *, jobject);

/** Class: jni_CHelloWorld* Method: hello* Signature: (Ljava/lang/String;I)Ljava/lang/String;*/

JNIEXPORT jstring JNICALL Java_jni_CHelloWorld_hello__Ljava_lang_String_2I(JNIEnv *, jobject, jstring, jint);

Page 13: Getting started with the JNI

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

Page 14: Getting started with the JNI

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 .\src\native -cp .\bin\java jni.CHelloWorld

Page 15: Getting started with the JNI

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.

Page 16: Getting started with the JNI

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

Page 17: Getting started with the JNI

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.

Page 18: Getting started with the JNI

Note on C++

#include <jni.h>

extern ”C” {

jstring Java_jni_CHelloWorld_hello(JNIEnv *env, jobject thiz) {

return env->NewStringUTF("hello, world (from JNI)");

}

}

Page 19: Getting started with the JNI

Arguments of a primitive type passed by value

Java Type Native Type Constantsboolean jboolean JNI_FALSE, JNI_TRUEbyte jbytechar jcharshort jshortint jintlong jlongfloat jfloatdouble jdoublevoid void

jsize scalar values and sizes

Page 20: Getting started with the JNI

Reference types

Reference types passed “by reference”. Here is native method hierarchy:

Page 21: Getting started with the JNI

Accessing Stringsjstring Java_jni_CHelloWorld_hello__Ljava_lang_String_2I

(JNIEnv* env, jobject thiz, jstring what, jint count) {

char dest[30];

/* Obtain string characters */const char* str = (*env)->GetStringUTFChars(env, what, 0);

strcpy(dest, “hello, “);strncat(dest, str, 22);

/* Relase characters to avoid memory leak */(*env)->ReleaseStringUTFChars(env, what, str);

return (*env)->NewStringUTF(env, dest);

}

Page 22: Getting started with the JNI

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);

Page 23: Getting started with the JNI

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

Page 24: Getting started with the JNI

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;}

Page 25: Getting started with the JNI

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 booleanB byteC charS shortI intJ longF floatD double

Lfully-qualified-class; fully-qualified-class

[type type[]

(arg-types)ret-type method type

Page 26: Getting started with the JNI

VM Signature example

Example Java method signature

long foo(int n, String s, int[] arr);

JVM Type signature:

(ILjava/lang/String;[I)J

Page 27: Getting started with the JNI
Page 28: Getting started with the JNI

javap tool

javap is Java Class File disassembler tool that comes to rescue

$ javap -s -p -cp .\bin\java jni.CHelloWorld

Page 29: Getting started with the JNI

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

Page 30: Getting started with the JNI

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, … );

Page 31: Getting started with the JNI

Static method invocation

- Find correct class if needed

jclass cl = FindClass(env, "java/lang/String");

- Find static method

jmethodID methodId = (*env)->GetStaticMethodID(env, cl, "copyValueOf", "([C)Ljava/lang/String;");

- Call using correct invocation method

jobject o = (*env)->CallStaticObjectMethod(env, cl, methodId, /* NativeTypes */ … );

Page 32: Getting started with the JNI

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);

Page 33: Getting started with the JNI

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);

Page 34: Getting started with the JNI

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);

Page 35: Getting started with the JNI

Throwing an exception

jint Throw(JNIEnv *env, jthrowable obj);

jint ThrowNew(JNIEnv *env, jclass clazz, const char *message);

void FatalError(JNIEnv *env, const char *msg);

Page 36: Getting started with the JNI

Usefull references

https://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx

http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html

http://www.ibm.com/support/knowledgecenter/SSYKE2_7.0.0/com.ibm.java.lnx.70.doc/diag/understanding/jni.html