Java本地介面

JNI 編寫的，並且被編譯為基於本機硬體和作業系統的程式。設計目的和功能.有些事情Java無法處理時，JNI允許程式設計師用其他程式語言來解決，例如，Java標準庫不支援的平臺相關功能或者程式庫。也用於改造已存在的用其它語言寫的程式，供Java程式呼叫。許多基於JNI的標準庫提供了很多功能給程式設計師使用，例如檔案I/O、音訊相關的功能。當然，也有各種高效能的程式，以及平臺相關的API實現，允許所有Java應用程式安全並且平臺獨立地使用這些功能。JNI框架允許Native方法呼叫Java物件，就像Java程式訪問Native物件一樣方便。Native方法可以建立Java物件，讀取這些物件，並呼叫Java物件執行某些方法。當然Native方法也可以讀取由Java程式自身建立的物件，並呼叫這些物件的方法。JNI如何工作.在JNI框架，native方法一般在單獨的.c或.cpp檔案中實現。當JVM呼叫這些函式，就傳遞一個codice_1指標，一個codice_2的指標，任何在Java方法中宣告的Java引數。一個JNI函式看起來類似這樣：JNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj)/*Implement Native Method Here*/"codice_3"指向一個結構包含了到JVM的介面，包含了所有必須的函式與JVM互動、訪問Java物件。例如，把本地陣列轉換為Java陣列的JNI函式，把本地字串轉換為Java字串的JNI函式，例項化物件，丟擲異常等。基本上，Java程式可以做的任何事情都可以用codice_1做到，雖然相當不容易。例如，下面程式碼把Java字串轉化為本地字串：//C++ codeextern "C"JNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj, jstring javaString)//Get the native string from javaStringconst char *nativeString = env-&gt;GetStringUTFChars(javaString, 0);//Do something with the nativeString//DON'T FORGET THIS LINE!!!env-&gt;ReleaseStringUTFChars(javaString, nativeString);/*C code*/JNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj, jstring javaString)/*Get the native string from javaString*/const char *nativeString = (*env)-&gt;GetStringUTFChars(env, javaString, 0);/*Do something with the nativeString*//*DON'T FORGET THIS LINE!!!*/(*env)-&gt;ReleaseStringUTFChars(env, javaString, nativeString);/*Objective-C code*/JNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj, jstring javaString)/*DON'T FORGET THIS LINE!!!*/JNF_COCOA_ENTER(env);/*Get the native string from javaString*/NSString* nativeString = JNFJavaToNSString(env, javaString);/*Do something with the nativeString*//*DON'T FORGET THIS LINE!!!*/JNF_COCOA_EXIT(env);本地資料型別與Java資料型別可以互相對映。對於複合資料型別，如物件，陣列，字串，就必須用codice_1中的方法來顯示地轉換。第2個引數"obj"引用到一個Java物件，在其中聲明瞭本地方法。型別對映.下表是Java (JNI)與原生代碼之間的資料型別對映：簽名codice_6是由該名字指明的類。例如，簽名codice_7是類codice_8。帶字首codice_9的簽名表示該型別的陣列，如codice_10表示整型陣列。codice_11簽名使用codice_12程式碼。這些型別是可以互換的，如codice_13也可使用 codice_14，不需任何型別轉換。但是，Java字串、陣列與本地字串、陣列是不同的。如果在使用codice_15代替了codice_16，程式可能會導致JVM崩潰。JNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj, jstring javaString) {// printf("%s", javaString); // INCORRECT: Could crash VM!// Correct way: Create and release native string from Java stringconst char *nativeString = (*env)-&gt;GetStringUTFChars(env, javaString, 0);printf("%s", nativeString);(*env)-&gt;ReleaseStringUTFChars(env, javaString, nativeString);這種情況也適用於Java陣列。下例對陣列元素求和。JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) {jint buf[10];jint i, sum = 0;// This line is necessary, since Java arrays are not guaranteed// to have a continuous memory layout like C arrays.env-&gt;GetIntArrayRegion(arr, 0, 10, buf);for (i = 0; i DetachCurrentThread (g_vm);高階使用.本地AWT繪製.原生代碼不僅可以與Java互動，也可以在Java 繪圖，使用。訪問彙編程式碼.JNI允許直接訪問彙編程式碼。 也可以從彙編程式碼訪問Java。Microsoft的RNI.Microsoft實現的Java虛擬機器——Visual J++的類似的訪問本地Windows程式碼的機制Raw Native Interface。例子.HelloWorld.make.shexport LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.javac HelloWorld.javajavah HelloWorldgcc -shared libHelloWorld.c -o libHelloWorld.sojava HelloWorldbuild.batMicrosoft Visual Studio 2012 Visual C++ compilerSET VC="C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC"Microsoft Windows SDK for Windows 7 and .NET Framework 4SET MSDK="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A"Java 1.7.0 update 21SET JAVA_HOME="C:\Program Files (x86)\Java\jdk1.7.0_21"call %VC%\vcvarsall.batjavac HelloWorld.javajavah HelloWorld%VC%\bin\cl /I%JAVA_HOME%\include /I%JAVA_HOME%\include\win32 /I%VC%\include /I%VC%\lib /I%MSDK%\Lib libHelloWorld.c /FelibHelloWorld.dll /LDjava HelloWorldHelloWorld.javaclass HelloWorldprivate native void print();public static void main(String[] args)new HelloWorld().print();static{System.loadLibrary("HelloWorld");HelloWorld.h/* DO NOT EDIT THIS FILE - it is machine generated *//* Header for class HelloWorld */extern "C" {* Class: HelloWorld* Method: print* Signature: ()VJNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *, jobject);libHelloWorld.c#include#include "HelloWorld.h"JNIEXPORT void JNICALLJava_HelloWorld_print(JNIEnv *env, jobject obj)printf("Hello World!\n");return;Invocation:$ chmod +x make.sh$ ./make.sh相關書籍.