JNI 入門

JNI 表示 Java Native Interface。它是一種如何從在 JVM 控制下執行的 Java 應用程式呼叫本機程式碼的機制,反之亦然。本機程式碼表示為目標平臺編譯的程式碼。本機程式碼通常用 C 或 C++編寫,但它可以用任何具有目標平臺編譯器的語言編寫。

JNI 非常有用

  • Java 應用程式需要訪問特定於平臺的資源,並且沒有具有所需功能的 Java 庫。資源可以是特定的硬體,感測器或其他。
  • Java 應用程式必須執行效能關鍵任務,本機程式碼可能比 java 位元組碼更快或佔用空間更少。儘管如此,確實過於自信 JVM 能夠進行大量的優化,而 C / C++中的天真實現可能會更慢。
  • C / C++(或其他語言)中的應用程式想要使用 java 庫中提供的功能。

從 JNI 開始,你需要

  • JDK 或能夠將 java 編譯為位元組碼的東西。
  • 用於編譯本機程式碼的編譯器。

以下 hello world 示例是一個呼叫 C 函式的簡單 Java 應用程式。該示例可以由 javac 從 JDK 和 gcc C 編譯器編譯。

Java 程式碼:

public class JNIExample {

    public static void main(String[] args) {
       // The loadLibrary search for the native library (libnative.so in this case)
       System.loadLibrary("native");
       String s = "Hello JNI";
       JNIExample example = new JNIExample();
       example.doPrint(s);
   }

   // The method with native code (written in C) must be declared with native prefix
   public native void doPrint(String message);

}

C 程式碼:

#include <jni.h>
#include <stdio.h>

/* the function that is called from java must be declered with decorators
 * JNIEXPORT and JNICALL.
 * The function name is constructed as Java_ClassName_MethodName
 * Function parameters correspond parameters in java but there are 2 extra parameters
 * JNIEnv is a pointer to java envoronmet and jobject is a reference to caller object.
 * Caller object is the instance of the JNIExample in this case.
 */
JNIEXPORT void JNICALL Java_JNIExample_doPrint(JNIEnv *e, jobject obj, jstring message) {
    const char *c_message;
    /* It is necessary to convert java objects like string to something C native */
    c_message = (*e)->GetStringUTFChars(e, message, NULL);
    printf("%s\n", c_message);
    /* in the end it is necessary to free resources allocated by Get above */
    (*e)->ReleaseStringUTFChars(e, message, c_message);
}