JNI 靜態(tài)注冊與動態(tài)注冊

靜態(tài)注冊

原理:根據(jù)函數(shù)名來建立 java 方法與 JNI 函數(shù)的一一對應(yīng)關(guān)系预厌;

實現(xiàn)流程:

  1. 編寫 java 代碼樊零;
  2. 利用 javah 指令生成對應(yīng)的 .h 文件府怯;
  3. 對 .h 中的聲明進行實現(xiàn);

弊端:

  1. 編寫不方便玫镐,JNI 方法名字必須遵循規(guī)則且名字很長辅柴;
  2. 編寫過程步驟多箩溃,不方便;
  3. 程序運行效率低碌嘀,因為初次調(diào)用native函數(shù)時需要根據(jù)根據(jù)函數(shù)名在JNI層中搜索對應(yīng)的本地函數(shù)碾篡,然后建立對應(yīng)關(guān)系,這個過程比較耗時筏餐;
JNIEXPORT jstring JNICALL
Java_com_example_efan_jni_1learn2_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

動態(tài)注冊

原理:利用 RegisterNatives 方法來注冊 java 方法與 JNI 函數(shù)的一一對應(yīng)關(guān)系开泽;

實現(xiàn)流程:

  1. 利用結(jié)構(gòu)體 JNINativeMethod 數(shù)組記錄 java 方法與 JNI 函數(shù)的對應(yīng)關(guān)系;
  2. 實現(xiàn) JNI_OnLoad 方法魁瞪,在加載動態(tài)庫后穆律,執(zhí)行動態(tài)注冊;
  3. 調(diào)用 FindClass 方法导俘,獲取 java 對象峦耘;
  4. 調(diào)用 RegisterNatives 方法,傳入 java 對象旅薄,以及 JNINativeMethod 數(shù)組辅髓,以及注冊數(shù)目完成注冊泣崩;

優(yōu)點:

  1. 流程更加清晰可控;
  2. 效率更高洛口;
jstring stringFromJNI(JNIEnv *env, jobject thiz){
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

static const JNINativeMethod gMethods[] = {
        {"stringFromJNI", "()Ljava/lang/String;", (jstring*)stringFromJNI}
};

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){

    __android_log_print(ANDROID_LOG_INFO, "native", "Jni_OnLoad");
    JNIEnv* env = NULL;
    if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) //從JavaVM獲取JNIEnv矫付,一般使用1.4的版本
        return -1;
    jclass clazz = env->FindClass("com/example/efan/jni_learn2/MainActivity");
    if (!clazz){
        __android_log_print(ANDROID_LOG_INFO, "native", "cannot get class: com/example/efan/jni_learn2/MainActivity");
        return -1;
    }
    if(env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])))
    {
        __android_log_print(ANDROID_LOG_INFO, "native", "register native method failed!\n");
        return -1;
    }
    return JNI_VERSION_1_4;
}

JNINativeMethod

在動態(tài)注冊的過程中使用到了結(jié)構(gòu)體 JNINativeMethod 用于記錄 java 方法與 jni 函數(shù)的對應(yīng)關(guān)系

typedef struct {
    const char* name;
    const char* signature;
    void*       fnPtr;
} JNINativeMethod;

結(jié)構(gòu)體的第一個參數(shù) name 是java 方法名;

第二個參數(shù) signature 用于描述方法的參數(shù)與返回值第焰;

第三個參數(shù) fnPtr 是函數(shù)指針买优,指向 jni 函數(shù);

其中挺举,第二個參數(shù) signature 使用字符串記錄方法的參數(shù)與返回值杀赢,具體格式形如“()V”、“(II)V”湘纵,其中分為兩部分脂崔,括號內(nèi)表示的是參數(shù),括號右側(cè)表示的是返回值梧喷;

數(shù)據(jù)類型映射

  1. 基本數(shù)據(jù)類型
java 類型 native 類型 域描述符 補充
boolean jboolean Z
byte jbyte B
char jchar C
short jshort S
int jint I
long jlong J
float jfloat F
double jdouble D
void void V
  1. 數(shù)組引用類型

    如果是一維數(shù)組則遵循下表脱篙,如果是二維數(shù)組或更高維數(shù)組則對應(yīng)的 native 類型為 jobjectArray,域描述符中使用 '[' 的個數(shù)表示維數(shù)

java 類型 native 類型 域描述符 補充
int[] jintArray [I
float[] jfloatArray [f
byte[] jbyteArray [B
char[] jcharArray [C
short[] jshortArray [S
double[] jdoubleArray [D
long[] jlongArray [F
boolean[] jbooleanArray [Z
  1. 對象引用類型

對于其它引用類型伤柄,即 java 中的對象,其映射規(guī)則為

java 類型 native 類型 域描述符 補充
類名(如 Surface) 通常是 jobject文搂,僅有一種例外适刀,如果 java 類型是 String,則對應(yīng)的native 類型是 jstring 以"L"開頭煤蹭,以";"結(jié)尾中間是用"/" 隔開的包及類名(如 Landroid/view/Surface;)如果內(nèi)部類則使用$連接內(nèi)部類笔喉;
  1. 對象數(shù)組引用類型

    如果是一維數(shù)組則遵循下表,如果是二維數(shù)組或更高維數(shù)組則對應(yīng)的 native 類型為 jobjectArray硝皂,域描述符中使用 '[' 的個數(shù)表示維數(shù)

java 類型 native 類型 域描述符 補充
類名(如 Surface) 通常是 jobject常挚,僅有一種例外,如果 java 類型是 String稽物,則對應(yīng)的native 類型是 jstring 在對象引用類型的域描述符的基礎(chǔ)上在左邊添加'['字符

jni 函數(shù)默認參數(shù)

在 jni 函數(shù)中有兩個默認參數(shù)

JNIEnv *env, jobject thiz

其中 JNIEnv 指代的是當前 java 環(huán)境奄毡,可以利用 JNIEnv 可以操作 java 層代碼;jobject 指代的是 jni 函數(shù)對應(yīng)的 java native 方法的類實例贝或,如果 java 方法是 static吼过,則代表的是 class 對象;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咪奖,一起剝皮案震驚了整個濱河市盗忱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羊赵,老刑警劉巖趟佃,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡闲昭,警方通過查閱死者的電腦和手機罐寨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汤纸,“玉大人衩茸,你說我怎么就攤上這事≈ⅲ” “怎么了楞慈?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長啃擦。 經(jīng)常有香客問我囊蓝,道長,這世上最難降的妖魔是什么令蛉? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任聚霜,我火速辦了婚禮,結(jié)果婚禮上珠叔,老公的妹妹穿的比我還像新娘蝎宇。我一直安慰自己,他們只是感情好祷安,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布姥芥。 她就那樣靜靜地躺著,像睡著了一般汇鞭。 火紅的嫁衣襯著肌膚如雪凉唐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天霍骄,我揣著相機與錄音台囱,去河邊找鬼。 笑死读整,一個胖子當著我的面吹牛簿训,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播米间,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼煎楣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了车伞?” 一聲冷哼從身側(cè)響起择懂,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎另玖,沒想到半個月后困曙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體表伦,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年慷丽,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹦哼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡要糊,死狀恐怖纲熏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锄俄,我是刑警寧澤局劲,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站奶赠,受9級特大地震影響鱼填,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毅戈,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一苹丸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苇经,春花似錦赘理、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至令花,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凉倚,已是汗流浹背兼都。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留稽寒,地道東北人扮碧。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像杏糙,于是被迫代替她去往敵國和親慎王。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355