Java Native Interface (JNI)

The Java Native Interface (JNI) is a framework that allows Java code running in a Java Virtual Machine (JVM) to call and to be called by native applications and libraries written in other languages.

Purpose

Handle situations when an application cannot be written entirely in the Java.

1. Standard Java class library does not support the platform-specific features.

2. Used for time-critical calculations or operations like solving complicated mathematical equations.

3. Using existing native applications and libraries.

Drawback

1. Losing some features of Java: the platform portability and type-safe and secure..

2. The JNI framework does NOT provide any automatic garbage collection for non-JVM memory resource allocated by native side.

3. Error checking is a MUST or it has the potential to crash the JNI side and the JVM.


Overview

This is the procedure of the Java code to call c library through JNI.

Step in writing and running a program.


HelloWorld.java

class HelloWorld {
private native void print();
static {
System.loadLibrary("HelloWorld");
}

public static void main(String[] args) {
new HelloWorld().print();
}
}

Creating HelloWorld.class by compiling,
javac HelloWorld.java


Using javah to create the JNI header file of c code
javah -jni HelloWorld
HelloWorld.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

The tool of checking the Signature of each method:
javap –c –p HelloWorld
HelloWrold.c

#include
#include
#include "HelloWorld.h"

JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}

Build the binary and shared library
gcc HelloWorld.c –c –I/[JDK PATH]
gcc –shared –o libHelloWorld.so HelloWorld.o
Finally, execute it!
javac HelloWorld

Native Method Arguments

The JNIEnv is the interface pointer, points to a location that contains a pointer to a function table. Each entry in the function table points to a JNI function.

Mapping of Types

There are two kinds of types in the Java: primitive types and reference types.

The mapping of primitive type is straightforward. The JNI passes objects to native methods as opaque references. The native code must access via the appropriate JNI functions.


JNIEXPORT jstring JNICALL Java_Prompt_getLine
(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const jbyte *str;
str = (*env)->GetStringUTFChars(env, prompt, NULL);
if(str == NULL) {
return NULL;
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
/* We assume here that the user does not type more than
* 127 characters */
scanf("%s", buf);
return (*env)->NewStringUTF(env, buf);
}


Reference:
Java Native Interface: Programmer's Guide and Specification
Java Native Interface - Wikipedia
The JavaTM Virtual Machine Specification

留言

kaku26寫道…
文中提到的是基礎的作法,使用javah -jni來產生native side的header檔。在Android source code中,是使用載入library時,呼叫JNI_OnLoad去register JNINativeMethod table的方法去讓java可以更有彈性的去使用native code。

這個網誌中的熱門文章

逃得了一時 逃不了一世

Google Hangouts

我老闆是真男人!