簡(jiǎn)介
最近項(xiàng)目中經(jīng)常使用到JNI,在這里記錄總結(jié)一下。
JNI是什么达罗?
????????JNI(Java Native Interface)譯為JAVA本地接口調(diào)用,它允許Java代碼和其他語(yǔ)言(主要是C與C++)寫的代碼進(jìn)行交互静秆,簡(jiǎn)單的說(shuō)粮揉,一種在Java虛擬機(jī)控制下執(zhí)行代碼的標(biāo)準(zhǔn)機(jī)制。
NDK是什么抚笔?
????????Android NDK(Android Native Development Kit )是一套android本地開發(fā)工具集合扶认,允許你用像C與C++語(yǔ)言那樣實(shí)現(xiàn)應(yīng)用程序的一部分。
為什么要使用NDK開發(fā)殊橙?
????????1辐宾、安全性,java是半解釋型語(yǔ)言膨蛮,很容易被反匯編后拿到源代碼文件叠纹,我們可以在重要的交互功能使用C或C++語(yǔ)言代替。
????????2敞葛、效率吊洼,C或C++語(yǔ)言比起java來(lái)說(shuō)效率要高出很多。
JNI和NDK的區(qū)別制肮?
????????從工具上說(shuō)冒窍,NDK其實(shí)多了一個(gè)把.so和.apk打包的工具,而JNI開發(fā)并沒有打包豺鼻,只是把.so文件放到文件系統(tǒng)的特定位置上面综液。
????????從編譯庫(kù)說(shuō),NDK開發(fā)C或C++只能能使用NDK自帶的有限的頭文件儒飒,而使用JNI則可以使用文件系統(tǒng)中帶的頭文件谬莹。
????????從編寫方式說(shuō),它們一樣。
JNI 相關(guān)元素
1附帽、JNI組織結(jié)構(gòu)
????????JNI函數(shù)表的組成就像C++的虛函數(shù)表埠戳,虛擬機(jī)可以運(yùn)行多張函數(shù)表。JNI接口指針僅在當(dāng)前線程中起作用蕉扮,指針不能從一個(gè)線程進(jìn)入另一個(gè)線程整胃,但可以在不同的線程中調(diào)用本地方法。
2喳钟、原始數(shù)據(jù)
3屁使、Java類型和JNI類型對(duì)應(yīng)表
4、JNI域描述符
引用類型則為 L + 該類型類描述符 + 奔则。
數(shù)組蛮寂,其為 : [ + 其類型的域描述符 + 。
多維數(shù)組則是 n個(gè)[ +該類型的域描述符 , N代表的是幾維數(shù)組易茬。
String類型的域描述符為 Ljava/lang/String;[ + 其類型的域描述符 + ;int[ ] 其描述符為[Ifloat[ ] 其描述符為[FString[ ] 其描述符為[Ljava/lang/String;Object[ ]類型的域描述符為[Ljava/lang/Object;int [ ][ ] 其描述符為[[Ifloat[ ][ ] 其描述符為[[F
將參數(shù)類型的域描述符按照申明順序放入一對(duì)括號(hào)中后跟返回值類型的域描述符酬蹋,規(guī)則如下: (參數(shù)的域描述符的疊加)返回類型描述符。對(duì)于抽莱,沒有返回值的范抓,用V(表示void型)表示。
舉例如下:
Java層方法 JNI函數(shù)簽名String test ( ) Ljava/lang/String;int f (int i, Object object) (ILjava/lang/Object;)Ivoid set (byte[ ] bytes) ([B)V
JNIEnv與JavaVM 概念
1岸蜗、JNIEnv 概念 : 是一個(gè)線程相關(guān)的結(jié)構(gòu)體, 該結(jié)構(gòu)體代表了 Java 在本線程的運(yùn)行環(huán)境 ;
2尉咕、JNIEnv 與 JavaVM :
?????注意區(qū)分這兩個(gè)概念;
(1)JavaVM : JavaVM 是 Java虛擬機(jī)在 JNI 層的代表, JNI 全局只有一個(gè);
(2)JNIEnv : JavaVM 在線程中的代表, 每個(gè)線程都有一個(gè), JNI 中可能有很多個(gè) JNIEnv;
3叠蝇、JNIEnv 作用 :
(1)調(diào)用 Java 函數(shù) : JNIEnv 代表 Java 運(yùn)行環(huán)境, 可以使用 JNIEnv 調(diào)用 Java 中的代碼;
(2)操作 Java 對(duì)象 : Java 對(duì)象傳入 JNI 層就是 Jobject 對(duì)象, 需要使用 JNIEnv 來(lái)操作這個(gè) Java 對(duì)象;
4璃岳、JNIEnv 體系結(jié)構(gòu)
線程相關(guān) : JNIEnv 是線程相關(guān)的, 即 在 每個(gè)線程中 都有一個(gè) JNIEnv 指針, 每個(gè)JNIEnv 都是線程專有的, 其它線程不能使用本線程中的 JNIEnv, 線程 A 不能調(diào)用 線程 B 的 JNIEnv;
5、JNIEnv 不能跨線程 :
(1) 當(dāng)前線程有效 : JNIEnv 只在當(dāng)前線程有效, JNIEnv 不能在 線程之間進(jìn)行傳遞, 在同一個(gè)線程中, 多次調(diào)用 JNI層方法, 傳入的 JNIEnv 是相同的;
(2) 本地方法匹配多JNIEnv : 在 Java 層定義的本地方法, 可以在不同的線程調(diào)用, 因此 可以接受不同的 JNIEnv;
JNIEnv 結(jié)構(gòu) : 由上面的代碼可以得出, JNIEnv 是一個(gè)指針, 指向一個(gè)線程相關(guān)的結(jié)構(gòu), 線程相關(guān)結(jié)構(gòu)指向 JNI 函數(shù)指針 數(shù)組, 這個(gè)數(shù)組中存放了大量的 JNI 函數(shù)指針, 這些指針指向了具體的 JNI 函數(shù);
注意:JNIEnv只在當(dāng)前線程中有效悔捶。本地方法不能將JNIEnv從一個(gè)線程傳遞到另一個(gè)線程中铃慷。相同的 Java 線程中對(duì)本地方法多次調(diào)用時(shí),傳遞給該本地方法的JNIEnv是相同的蜕该。但是犁柜,一個(gè)本地方法可被不同的 Java 線程所調(diào)用,因此可以接受不同的 JNIEnv堂淡。
更多經(jīng)驗(yàn)持續(xù)更新...