? ??一切諸法性皆如是渠缕,唯是自心分別境界鸽素。凡夫迷惑不能解了,無(wú)有能見(jiàn)亦無(wú)所見(jiàn)亦鳞,無(wú)有能說(shuō)亦無(wú)所說(shuō)馍忽,見(jiàn)佛聞法皆是分別,如向所說(shuō)不能見(jiàn)佛燕差,不起分別是則能見(jiàn)遭笋。? ? ? ? ? ??----------佛說(shuō)
JNI編程
JNI是一種本地編程接口。它允許運(yùn)行在JAVA虛擬機(jī)中的JAVA代碼和用其他編程語(yǔ)言徒探,諸如C語(yǔ)言坐梯、C++、匯編刹帕,寫(xiě)的應(yīng)用和庫(kù)之間的交互操作吵血。
JNI數(shù)據(jù)類(lèi)型
JNIEXPORT?和?JNICALL谎替,定義在`jni_md.h`頭文件中。
JNIEXPORT:
? ??在?Windows?中,定義為`__declspec(dllexport)`蹋辅。因?yàn)閃indows編譯?dll?動(dòng)態(tài)庫(kù)規(guī)定钱贯,如果動(dòng)態(tài)庫(kù)中的函數(shù)要被外部調(diào)用,需要在函數(shù)聲明中添加此標(biāo)識(shí)侦另,表示將該函數(shù)導(dǎo)出在外部可以調(diào)用秩命。
在?Linux/Unix/Mac?os/Android?這種?Like?Unix系統(tǒng)中,定義為`__attribute__?((visibility?("default")))`GCC?有個(gè)visibility屬性,?該屬性是說(shuō),?啟用這個(gè)屬性:
1.?當(dāng)-fvisibility=hidden時(shí)動(dòng)態(tài)庫(kù)中的函數(shù)默認(rèn)是被隱藏的即?hidden.?除非顯示聲明為`__attribute__((visibility("default")))`.
2 當(dāng)-fvisibility=default時(shí)動(dòng)態(tài)庫(kù)中的函數(shù)默認(rèn)是可見(jiàn)的.除非顯示聲明為`__attribute__((visibility("hidden")))`.
JNICALL:
在類(lèi)Unix中無(wú)定義褒傅,在Windows中定義為:`_stdcall??`?弃锐,一種函數(shù)調(diào)用約定 。類(lèi)Unix系統(tǒng)中這兩個(gè)宏可以省略不加
C/C++中獲取java的數(shù)組
C/C++反射Java
1在C/C++中反射創(chuàng)建Java的對(duì)象殿托,調(diào)用Java的方法
基本數(shù)據(jù)類(lèi)型的簽名采用一系列大寫(xiě)字母來(lái)表示, 如下表所示:
可以使用javap來(lái)獲取反射方法時(shí)的簽名
? ??????cd 進(jìn)入 class所在的目錄 執(zhí)行: javap -s 全限定名,查看輸出的 descriptor
反射屬性
JNI引用
在?JNI?規(guī)范中定義了三種引用:局部引用(Local?Reference)霹菊、全局引用(Global?Reference)、弱全局引用(Weak?Global?Reference)支竹。
????局部引用
? ?大多數(shù)JNI函數(shù)會(huì)創(chuàng)建局部引用旋廷。NewObject/FindClass/NewStringUTF?等等都是局部引用。
? ???局部引用只有在創(chuàng)建它的本地方法返回前有效,本地方法返回后礼搁,局部引用會(huì)被自動(dòng)釋放饶碘。
? ??因此無(wú)法跨線程、跨方法使用馒吴。
釋放一個(gè)局部引用有兩種方式:
1扎运、本地方法執(zhí)行完畢后VM自動(dòng)釋放;??2饮戳、通過(guò)DeleteLocalRef手動(dòng)釋放绪囱;
VM會(huì)自動(dòng)釋放局部引用,為什么還需要手動(dòng)釋放呢莹捡?因?yàn)榫植恳脮?huì)阻止它所引用的對(duì)象被GC回收鬼吵。
全局引用
?全局引用可以跨方法、跨線程使用篮赢,直到它被手動(dòng)釋放才會(huì)失效 齿椅。
由 NewGlobalRef 函數(shù)創(chuàng)建
弱引用
與全局引用類(lèi)似,弱引用可以跨方法启泣、線程使用涣脚。與全局引用不同的是,弱引用不會(huì)阻止GC回收它所指向的VM內(nèi)部的對(duì)象?寥茫。
在對(duì)Class進(jìn)行弱引用是非常合適(FindClass)遣蚀,因?yàn)镃lass一般直到程序進(jìn)程結(jié)束才會(huì)卸載。
在使用弱引用時(shí),必須先檢查緩存過(guò)的弱引用是指向活動(dòng)的對(duì)象芭梯,還是指向一個(gè)已經(jīng)被GC的對(duì)象
JNI_OnLoad函數(shù)
調(diào)用System.loadLibrary()函數(shù)時(shí)险耀, 內(nèi)部就會(huì)去查找so中的 JNI_OnLoad 函數(shù),如果存在此函數(shù)則調(diào)用玖喘。
JNI_OnLoad會(huì):
告訴 VM 此 native 組件使用的 JNI 版本甩牺。
對(duì)應(yīng)了Java版本,android中只支持JNI_VERSION_1_2 累奈、JNI_VERSION_1_4贬派、JNI_VERSION_1_6
在JDK1.8有 JNI_VERSION_1_8。
動(dòng)態(tài)注冊(cè)
1 在此之前我們一直在jni中使用的?Java_PACKAGENAME_CLASSNAME_METHODNAME?來(lái)進(jìn)行與java方法的匹配澎媒,這種方式我們稱(chēng)之為靜態(tài)注冊(cè)搞乏。
2 而動(dòng)態(tài)注冊(cè)則意味著方法名可以不用這么長(zhǎng)了,在android?aosp源碼中就大量的使用了動(dòng)態(tài)注冊(cè)的形式
native跨線程調(diào)用Java
? ???????native調(diào)用java需要使用JNIEnv這個(gè)結(jié)構(gòu)體戒努,而JNIEnv是由Jvm傳入與線程相關(guān)的變量请敦。
? ????????但是可以通過(guò)JavaVM的AttachCurrentThread方法來(lái)獲取到當(dāng)前線程中的JNIEnv指針。?