讀古今文學網 > Android程序設計:第2版 > 本地方法和JNI調用 >

本地方法和JNI調用

JNI制定了一些規範,支持其他語言調用它的方法。本地方法的變化(實質上是C或C++庫)大於Java代碼的變化。

本地方法調用規範

當虛擬機(VM)(在Android中,即Dalvik)調用C或C++實現的函數時,它會傳遞兩個特殊的參數:

·JNIEnv指針,指向虛擬機中調用本地方法的線程。

·Jobject指針,是調用類的引用。

這些參數會被「透明」地傳遞給Java代碼,也就是說,它們不會出現在聲明調用Java代碼的方法簽名中。Java調用只是顯式傳遞所調用的函數需要的其他任何參數。

JNI方法調用可能看起來如下:


/* sample method where the Java call passed no parameters */
void Java_ClassName_MethodName (JNIEnv *env, jobject obj) {
    /* do something */
}
/* another sample method with two parameters passed, returning a double */
jdouble Java_ClassName_MethodName ( JNIEnv* env, jobject obj,
                                                        jdouble x, jdouble y) {
    return x + y;
}
  

這些示例顯示了自動傳遞給每個本地方法的兩個參數,以及匹配Java類型的兩個參數。

當本地方法被調用時,它和調用它的Java代碼在相同的進程和線程中運行。正如我們在本章後面將要看到的,本地方法可以從Java堆中分配內存,以充分利用垃圾回收機制,或在Java堆外面分配內存,以避開Java內存管理。C或C++的代碼中在棧上分配的變量和這些語言的本地變量的語義相同。這些變量也是在它們所在的進程的棧空間中分配的。

JNI提供了和Java類型一致的類型,如表19-1所示。

表19-1:數據映射

表19-1:數據映射(續)

在復合類型中,如對像、數組和字符串等,本地代碼必須顯式調用轉換方法對數據進行轉換,這些轉換方法需要使用JNIEnv指針訪問。

Java端的規範

在Java類中使用本地方法之前,必須使用System.loadLibrary預先加載本地方法所在的庫。通常情況下,要使用本地方法的類會靜態加載這個方法。類中要被本地訪問的方法會使用關鍵字native來聲明。示例代碼如下:


public class ClassWithNativeMethod {
    public native double nativeMethod; // native method
    static {
        System.loadLibrary("sample"); // load lib called 'sample'
    }
    public static void main(String args) {
        ClassWithNativeMethod cwnm = new ClassWithNativeMethod;
        double answer = cwnm.nativeMethod; // call native method
        System.out.println("Answer is : "+answer);
    }
}