本站AI自動(dòng)判斷提供您所需要的app下載:點(diǎn)我下載安裝,你懂的APP
本篇文章給大家談?wù)劷焯?18c.mic,以及18c.mic網(wǎng)頁(yè)版的知識(shí)點(diǎn),希望對(duì)各位有所幫助,不要忘了收藏本站喔。
文章詳情介紹:
什么是JNI?為什么會(huì)有Native層?如何使用?
什么是JNI?JNI是Java Native Interface的縮寫(xiě),通過(guò)使用 Java本地接口書(shū)寫(xiě)程序,可以確保代碼在不同的平臺(tái)上方便移植;從Java1.1開(kāi)始,JNI標(biāo)準(zhǔn)成為java平臺(tái)的一部分,它允許Java代碼和其他語(yǔ)言寫(xiě)的代碼進(jìn)行交互
本地代碼與 Java 虛擬機(jī)之間是通過(guò) JNI 函數(shù)實(shí)現(xiàn)相互操作的;JNI 函數(shù)通過(guò)接口指針來(lái)獲得,本地方法將 JNI 接口指針當(dāng)作參數(shù)來(lái)接受;虛擬機(jī)保證在從相同的 Java 線程中對(duì)本地方法進(jìn)行多次調(diào)用時(shí),傳遞給本地方法的接口指針是相同的,本地方法被不同的 Java 線程調(diào)用時(shí),它接受不同的 JNI接口指針
使用JNI和算法進(jìn)行交互,主要是為了提高算法的性能,最大化的利用機(jī)器硬件資源
Android 中的語(yǔ)言層可以將語(yǔ)言層分成Java層和Native層;為什么會(huì)有Native層呢?是因?yàn)樵贘ava出現(xiàn)之前,很多的功能和系統(tǒng)都是由Native語(yǔ)言寫(xiě)的,所以Java出現(xiàn)之后就不必重復(fù)造輪子,直接調(diào)用這些方法就行了,而且Native層更接近匯編語(yǔ)言,所以性能更優(yōu)
所以代碼中就出現(xiàn)了Java層調(diào)用Native層的方法,而這個(gè)跨語(yǔ)言的調(diào)用過(guò)程就是 JNI
當(dāng)Java語(yǔ)言無(wú)法處理一些任務(wù)的時(shí)候,就可以使用JNI來(lái)完成
下面是幾個(gè) JNI 的應(yīng)用場(chǎng)景:需要調(diào)用Java語(yǔ)言不支持的依賴于操作系統(tǒng)平臺(tái)特性的一些功能
● 需要調(diào)用當(dāng)前UNIX系統(tǒng)的某個(gè)功能,而Java不支持這個(gè)功能的時(shí)候,就要用到JNI
● 在程序?qū)r(shí)間敏感或?qū)π阅芤筇貏e高時(shí),有必要用到更底層的語(yǔ)言來(lái)提高運(yùn)行效率
● 音視頻開(kāi)發(fā)涉及到的音視頻編解碼需要更快的處理速度,這就需要用到JNI
● 為了整合一些以前的非Java語(yǔ)言開(kāi)發(fā)的系統(tǒng)
● 需要用到早期實(shí)現(xiàn)的C/C++語(yǔ)言開(kāi)發(fā)的一些功能或者系統(tǒng),將這些功能整合到當(dāng)前的系統(tǒng)或者新的版本中
開(kāi)發(fā)一個(gè)手游價(jià)格(開(kāi)發(fā)一個(gè)手游游戲要多少錢) - 櫻花動(dòng)漫
JNI是完善Java的一個(gè)重要功能,它讓Java更加全面、封裝了各個(gè)平臺(tái)的差異性
jni異常處理在android ndk開(kāi)發(fā)過(guò)程中,調(diào)用java對(duì)象方法可能會(huì)拋異常,如果在ndk層中不做任何處理,那么程序就會(huì)直接崩潰;例如我們要在jni層獲取apk的簽名,代碼如下:
**jclass native_class = env->GetObjectClass(const_cast
上述代碼如果package_name查找不到就會(huì)報(bào)如下異常
捕獲異常
釋放資源
Native 提供了 ExceptionOccurred 和 ExceptionCheck 方法來(lái)檢測(cè)是否有異常發(fā)生,前者返回的是 jthrowable 類型,后者返回的是 jboolean 類型;如果有異常,會(huì)通過(guò) ExceptionDescribe 方法來(lái)打印異常信息,方便我們?cè)?LogCat 中看到對(duì)應(yīng)的信息
而 ExceptionClear 方法則是關(guān)鍵的不會(huì)讓?xiě)?yīng)用直接崩潰的方法,類似于 Java 的 catch 捕獲異常處理,它會(huì)消除這次異常;這樣就把由 Native 調(diào)用 Java 時(shí)的一個(gè)異常進(jìn)行了處理,當(dāng)處理完異常之后,別忘了釋放對(duì)應(yīng)的資源
不過(guò),我們這樣僅僅是消除了這次異常,還應(yīng)該讓調(diào)用者有異常的發(fā)生,那么就需要通過(guò) Native 來(lái)拋出一個(gè)異常告訴 Java 調(diào)用者了
void throwByName(JNIEnv *env, const char *name, const char *msg) {
jclass cls = env->FindClass(name);
if (cls != NULL) {
env->ThrowNew(cls, msg);
}
env->DeleteLocalRef(cls);
}
// 調(diào)用拋出異常
extern "C"
JNIEXPORT void JNICALL
Java_com_glumes_cppso_jnioperations_ExceptionOps_nativeThrowException(JNIEnv *env, jobject instance) {
throwByName(env, "java/lang/IllegalArgumentException", "native throw exception");
}
jni錯(cuò)誤日志分析
ndk發(fā)生崩潰的時(shí)候會(huì)在/data/tombstones文件夾下生成一個(gè)墓碑文件,形如tombstone_xx。谷歌也提供了addr2line/ objdump/ndk-stack工具
一個(gè)典型的墓碑文件內(nèi)容如下
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'
Revision: '0'
ABI: 'x86'
pid: 1019, tid: 1019, name: surfaceflinger >>> /system/bin/surfaceflinger <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
eax a6265c06 ebx b7467d88 ecx b7631a22 edx a6265c06
esi 00000000 edi b6867140
xcs 00000073 xds 0000007b xes 0000007b xfs 00000000 xss 0000007b
eip b745a639 ebp bfcfc1e8 esp bfcfc150 flags 00010282
backtrace:
#00 pc 00006639 /system/lib/libui.so (android::Fence::waitForever(char const*)+41)
#01 pc 00034b86 /system/lib/libsurfaceflinger.so
#02 pc 0003229e /system/lib/libsurfaceflinger.so
#03 pc 0002cb9c /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+652)
#04 pc 000342f4 /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2580)
#05 pc 0004eafb /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+411)
#06 pc 0004ce06 /system/lib/libgui.so (android::Surface::hook_queueBuffer(ANativeWindow*, ANativeWindowBuffer*, int)+38)
#07 pc 00014bc6 /system/lib/egl/libGLES_android.so
#08 pc 00017f73 /system/lib/egl/libGLES_android.so (eglSwapBuffers+163)
#09 pc 00015fdb /system/lib/libEGL.so (eglSwapBuffers+203)
#10 pc 000013ea /system/lib/hw/hwcomposer.x86.so
#11 pc 00034730 /system/lib/libsurfaceflinger.so
#12 pc 000256d4 /system/lib/libsurfaceflinger.so
#13 pc 00024bf4 /system/lib/libsurfaceflinger.so
#14 pc 000236fb /system/lib/libsurfaceflinger.so
#15 pc 0002338a /system/lib/libsurfaceflinger.so
#16 pc 0001e0ff /system/lib/libsurfaceflinger.so
#17 pc 0001d9ce /system/lib/libutils.so (android::Looper::pollInner(int)+926)
#18 pc 0001db73 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+67)
#19 pc 0001e561 /system/lib/libsurfaceflinger.so
#20 pc 00022ce7 /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::run()+39)
#21 pc 00000ca3 /system/bin/surfaceflinger
#22 pc 0001365a /system/lib/libc.so (__libc_init+106)
#23 pc 00000da8 /system/bin/surfaceflinger
stack:
bfcfc110 00000000
bfcfc114 b6839270
bfcfc118 00000000
bfcfc11c 00000000
bfcfc120 b68394e0
bfcfc124 00000002
bfcfc128 00000002
bfcfc12c b75d8185 /system/lib/libutils.so (android::RefBase::incStrong(void const*) const+53)
bfcfc130 b6839270
bfcfc134 bfcfc1e8 [stack]
bfcfc138 00000002
bfcfc13c a6265c06
bfcfc140 b7467d88 /system/lib/libui.so
bfcfc144 00000000
bfcfc148 b6867140
bfcfc14c b745a639 /system/lib/libui.so (android::Fence::waitForever(char const*)+41)
#00 bfcfc150 b683af18
bfcfc154 bfcfc1e8 [stack]
bfcfc158 00000000
bfcfc15c 00000000
bfcfc160 00000000
bfcfc164 b683af18
bfcfc168 b75ec9c4 /system/lib/libutils.so
bfcfc16c b75d8285 /system/lib/libutils.so (android::RefBase::weakref_type::decWeak(void const*)+37)
bfcfc170 00000000
bfcfc174 00000000
bfcfc178 00000000
bfcfc17c 00000000
bfcfc180 b7642968 /system/lib/libsurfaceflinger.so
bfcfc184 bfcfc1e8 [stack]
bfcfc188 b6867140
bfcfc18c b7622b87 /system/lib/libsurfaceflinger.so
文件結(jié)構(gòu)
定位工具addr2line
qinqundeMacBook-Pro% ./aarch64-linux-android-addr2line -C -f -e ~/Documents/DProtect2/mylibrary/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so 0000000000157efc
Java_com_dofun_dprotect_lib_LocalWork_start
/Users/qinqun/Documents/DProtect2/mylibrary/src/main/cpp/native-lib.cpp:147
ndk-stack
有需要完整代碼的同學(xué) 可以 私信 發(fā)送 “底層源碼” 即可 免費(fèi)獲取
現(xiàn)在發(fā)送還可以獲得更多《Android 學(xué)習(xí)筆記+源碼解析+面試視頻》
JNI 特點(diǎn):二進(jìn)制兼容
● 本地方法庫(kù)與同一平臺(tái)上所有Java 虛擬機(jī)之間實(shí)現(xiàn)二進(jìn)制兼容,即對(duì)于給定平臺(tái)開(kāi)發(fā)人員只需要維護(hù)一種版本的本地方法庫(kù)
效率高
為了實(shí)現(xiàn)實(shí)時(shí)系統(tǒng),JNI 在效率與虛擬機(jī)無(wú)關(guān)性之間進(jìn)行了優(yōu)化,以保障高效運(yùn)行
功能強(qiáng)
● JNI 提供了大量的函數(shù)及接口讓本地方法與Java 虛擬機(jī)內(nèi)核相互操作,增強(qiáng)兩者的功能
本地代碼與 Java 虛擬機(jī)之間是通過(guò) JNI 函數(shù)實(shí)現(xiàn)相互操作的;JNI 函數(shù)通過(guò)接口指針來(lái)獲得,本地方法將 JNI 接口指針當(dāng)作參數(shù)來(lái)接受;虛擬機(jī)保證在從相同的 Java 線程中對(duì)本地方法進(jìn)行多次調(diào)用時(shí),傳遞給本地方法的接口指針是相同的,本地方法被不同的 Java 線程調(diào)用時(shí),它接受不同的 JNI接口指針
尾述有需要完整代碼的同學(xué) 可以 私信 發(fā)送 “底層源碼” 即可 免費(fèi)獲取
現(xiàn)在發(fā)送還可以獲得更多《Android 學(xué)習(xí)筆記+源碼解析+面試視頻》
技術(shù)是無(wú)止境的,你需要對(duì)自己提交的每一行代碼、使用的每一個(gè)工具負(fù)責(zé),不斷挖掘其底層原理,才能使自己的技術(shù)升華到更高的層面
Android 架構(gòu)師之路還很漫長(zhǎng),與君共勉
魔域互通版手游體驗(yàn)服下載 - 櫻花動(dòng)漫
PS:有問(wèn)題歡迎指正,可以在評(píng)論區(qū)留下你的建議和感受;
歡迎大家點(diǎn)贊評(píng)論,覺(jué)得內(nèi)容可以的話,可以轉(zhuǎn)發(fā)分享一下