JNI 數(shù)據(jù)類(lèi)型與 Java 數(shù)據(jù)類(lèi)型的映射關(guān)系

當(dāng)我們?cè)谡{(diào)用一個(gè) Java native 方法的時(shí)候,方法中的參數(shù)是如何傳遞給 C/C++ 本地函數(shù)中的呢?Java 方法中的參數(shù)與 C/C++ 函數(shù)中的參數(shù),它們之間是怎么轉(zhuǎn)換的呢?我猜你應(yīng)該也有相關(guān)的疑慮吧,咱們先來(lái)看一個(gè)例子,還是以 HelloWorld 為例:
HelloWorld.java:

package com.study.jnilearn;  

class MyClass {}  

public class HelloWorld {  

    public static native void test(short s, int i, long l, float f, double d, char c,   
            boolean z, byte b, String str, Object obj, MyClass p, int[] arr);  

    public static void main(String[] args) {  
        String obj = "obj";  
        short s = 1;  
        long l = 20;  
        byte b = 127;  
        test(s, 1, l, 1.0f, 10.5, 'A', true, b, "中國(guó)", obj, new MyClass(), new int[] {});  
    }  

    static {  
        System.loadLibrary("HelloWorld");  
    }  
}  

在 HelloWorld.java 中定義了一個(gè) test 的 native 方法,該方法中一個(gè)共有 12 個(gè)參數(shù),其中前面 8 個(gè)為基本數(shù)據(jù)類(lèi)型,后面 4 個(gè)全部為引用類(lèi)型。
由 HelloWorld.class 生成的 native 函數(shù)原型及實(shí)現(xiàn):

/* 
 * Class:     com_study_jnilearn_HelloWorld 
 * Method:    test 
 * Signature: (SIJFDCZBLjava/lang/String;Ljava/lang/Object;Lcom/study/jnilearn/MyClass;[I)V 
 */  
JNIEXPORT void JNICALL Java_com_study_jnilearn_HelloWorld_test  
    (JNIEnv *env, jclass cls, jshort s, jint i, jlong l, jfloat f,  
     jdouble d, jchar c, jboolean z, jbyte b, jstring j_str, jobject jobj1, jobject job2, jintArray j_int_arr)  
{  
    printf("s=%hd, i=%d, l=%ld, f=%f, d=%lf, c=%c, z=%c, b=%d", s, i, l, f, d, c, z, b);  
    const char *c_str = NULL;  
    c_str = (*env)->GetStringUTFChars(env, j_str, NULL);  
    if (c_str == NULL)  
    {  
        return; // memory out  
    }  
    (*env)->ReleaseStringUTFChars(env, j_str, c_str);  
    printf("c_str: %s\n", (char*)c_str);  
}  

調(diào)用 test 方法的輸出結(jié)果:

Paste_Image.png

從頭文件函數(shù)的原型可以得知,test 方法中形參的數(shù)據(jù)類(lèi)型自動(dòng)轉(zhuǎn)換成了 JNI 中相應(yīng)的數(shù)據(jù)類(lèi)型,不難理解,在調(diào)用 Java native 方法將實(shí)參傳遞給 C/C++ 函數(shù)的時(shí)候,會(huì)自動(dòng)將 java 形參的數(shù)據(jù)類(lèi)型自動(dòng)轉(zhuǎn)換成 C/C++ 相應(yīng)的數(shù)據(jù)類(lèi)型,所以我們?cè)趯?xiě) JNI 程序的時(shí)候,必須要明白它們之間數(shù)據(jù)類(lèi)型的對(duì)應(yīng)關(guān)系。
在 Java 語(yǔ)言中數(shù)據(jù)類(lèi)型分為基本數(shù)據(jù)類(lèi)型和引用類(lèi)型,其中基本數(shù)據(jù)類(lèi)型有 8 種:byte、char、short、int、long、float、double、boolean,除了基本數(shù)據(jù)類(lèi)型外其它都是引用類(lèi)型:Object、String、數(shù)組等。8 種基本數(shù)據(jù)類(lèi)型分別對(duì)應(yīng)JNI數(shù)據(jù)類(lèi)型中的 jbyte、jchar、jshort、jint、jlong、jfloat、jdouble、jboolean。所有的 JNI 引用類(lèi)型全部是 jobject 類(lèi)型,為了使用方便和類(lèi)型安全,JNI 定義了一個(gè)引用類(lèi)型集合,集合當(dāng)中的所有類(lèi)型都是 jobject 的子類(lèi),這些子類(lèi)和 Java 中常用的引用類(lèi)型相對(duì)應(yīng)。例如:jstring 表示字符串、jclass 表示 class 字節(jié)碼對(duì)象、jthrowable 表示異常、jarray 表示數(shù)組,另外 jarray 派生了 8 個(gè)子類(lèi),分別對(duì)應(yīng)Java 中的 8 種基本數(shù)據(jù)類(lèi)型(jintArray、jshortArray、jlongArray等)。下面再回顧頭來(lái)看看 test 方法與Java_com_study_jnilearn_HelloWorld_test
函數(shù)中參數(shù)類(lèi)型的對(duì)應(yīng)關(guān)系:

// HelloWorld.java  
public static native void test(short s, int i, long l, float f, double d, char c,   
            boolean z, byte b, String str, Object obj, MyClass p);  

// HelloWorld.h  
JNIEXPORT void JNICALL Java_com_study_jnilearn_HelloWorld_test  
  (JNIEnv *, jclass, jshort, jint, jlong, jfloat, jdouble, jchar, jboolean, jbyte, jstring, jobject, jobject, jintArray);  

從上面兩個(gè)函數(shù)的參數(shù)中可以看出來(lái),除了 JNIEnv 和 jclass 這兩個(gè)參數(shù)外,其它參數(shù)都是一一對(duì)應(yīng)的。下面是JNI 規(guī)范文檔中描述 Java 與 JN I數(shù)據(jù)類(lèi)型的對(duì)應(yīng)關(guān)系:
基本數(shù)據(jù)類(lèi)型:

Paste_Image.png

引用類(lèi)型:



JNI 如果使用 C++ 語(yǔ)言編寫(xiě)的話(huà),所有引用類(lèi)型派生自 jobject,使用 C++ 的繼承結(jié)構(gòu)特性,使用相應(yīng)的類(lèi)型。如下所示:

class _jobject {};  
   class _jclass : public _jobject {};  
   class _jstring : public _jobject {};  
   class _jarray : public _jobject {};  
   class _jbooleanArray : public _jarray {};  
   class _jbyteArray : public _jarray {};  

JNI 如果使用 C 語(yǔ)言編寫(xiě)的話(huà),所有引用類(lèi)型使用 jobject,其它引用類(lèi)型使用 typedef 重新定義,如:typedef jobject jstring 。 jvalue 是一個(gè) unio(聯(lián)合)類(lèi)型,在 C 語(yǔ)中為了節(jié)約內(nèi)存,會(huì)用聯(lián)合類(lèi)型變量來(lái)存儲(chǔ)聲明在聯(lián)合體中的任意類(lèi)型數(shù)據(jù) 。在 JNI 中將基本數(shù)據(jù)類(lèi)型與引用類(lèi)型定義在一個(gè)聯(lián)合類(lèi)型中,表示用 jvalue 定義的變量,可以存儲(chǔ)任意 JNI 類(lèi)型的數(shù)據(jù),后面會(huì)介紹 jvalue 在 JNI 編程當(dāng)中的應(yīng)用。原型如下:

typedef union jvalue {  
    jboolean z;  
    jbyte    b;  
    jchar    c;  
    jshort   s;  
    jint     i;  
    jlong    j;  
    jfloat   f;  
    jdouble  d;  
    jobject  l;  
} jvalue;  

NdkDemo代碼已上傳至Github

如有不正支出,歡迎留言交流!
我的GitHub
我的CSDN
我的簡(jiǎn)書(shū)
開(kāi)發(fā)筆記

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容