禁慢天堂_18c.mic(18c.mic網頁版)


本站AI自動判斷提供您所需要的app下載:點我下載安裝,你懂的APP

本篇文章給大家談談禁慢天堂:18c.mic,以及18c.mic網頁版的知識點,希望對各位有所幫助,不要忘了收藏本站喔。

文章詳情介紹:

什么是JNI?為什么會有Native層?如何使用?

什么是JNI?

JNI是Java Native Interface的縮寫,通過使用 Java本地接口書寫程序,可以確保代碼在不同的平臺上方便移植;從Java1.1開始,JNI標準成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互

本地代碼與 Java 虛擬機之間是通過 JNI 函數實現相互操作的;JNI 函數通過接口指針來獲得,本地方法將 JNI 接口指針當作參數來接受;虛擬機保證在從相同的 Java 線程中對本地方法進行多次調用時,傳遞給本地方法的接口指針是相同的,本地方法被不同的 Java 線程調用時,它接受不同的 JNI接口指針

使用JNI和算法進行交互,主要是為了提高算法的性能,最大化的利用機器硬件資源

Android 中的語言層

可以將語言層分成Java層和Native層;為什么會有Native層呢?是因為在Java出現之前,很多的功能和系統都是由Native語言寫的,所以Java出現之后就不必重復造輪子,直接調用這些方法就行了,而且Native層更接近匯編語言,所以性能更優

所以代碼中就出現了Java層調用Native層的方法,而這個跨語言的調用過程就是 JNI

當Java語言無法處理一些任務的時候,就可以使用JNI來完成

下面是幾個 JNI 的應用場景:

需要調用Java語言不支持的依賴于操作系統平臺特性的一些功能

● 需要調用當前UNIX系統的某個功能,而Java不支持這個功能的時候,就要用到JNI

● 在程序對時間敏感或對性能要求特別高時,有必要用到更底層的語言來提高運行效率

● 音視頻開發涉及到的音視頻編解碼需要更快的處理速度,這就需要用到JNI

● 為了整合一些以前的非Java語言開發的系統

● 需要用到早期實現的C/C++語言開發的一些功能或者系統,將這些功能整合到當前的系統或者新的版本中

JNI是完善Java的一個重要功能,它讓Java更加全面、封裝了各個平臺的差異性

jni異常處理

在android ndk開發過程中,調用java對象方法可能會拋異常,如果在ndk層中不做任何處理,那么程序就會直接崩潰;例如我們要在jni層獲取apk的簽名,代碼如下:

**jclass native_class = env->GetObjectClass(const_cast(contextObject)); jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager", "()Landroid/content/pm/PackageManager;"); jobject pm_obj = env->CallObjectMethod(const_cast(contextObject), pm_id); jclass pm_clazz = env->GetObjectClass(pm_obj); jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); // 獲得應用包的信息 jobject pi_obj = NULL; //GET_SIGNATURES 64 pi_obj = env->CallObjectMethod(pm_obj, package_info_id, package_name, 64); ...**

上述代碼如果package_name查找不到就會報如下異常

捕獲異常

釋放資源

Native 提供了 ExceptionOccurred 和 ExceptionCheck 方法來檢測是否有異常發生,前者返回的是 jthrowable 類型,后者返回的是 jboolean 類型;如果有異常,會通過 ExceptionDescribe 方法來打印異常信息,方便我們在 LogCat 中看到對應的信息

而 ExceptionClear 方法則是關鍵的不會讓應用直接崩潰的方法,類似于 Java 的 catch 捕獲異常處理,它會消除這次異常;這樣就把由 Native 調用 Java 時的一個異常進行了處理,當處理完異常之后,別忘了釋放對應的資源

不過,我們這樣僅僅是消除了這次異常,還應該讓調用者有異常的發生,那么就需要通過 Native 來拋出一個異常告訴 Java 調用者了

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); } // 調用拋出異常 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錯誤日志分析

ndk發生崩潰的時候會在/data/tombstones文件夾下生成一個墓碑文件,形如tombstone_xx。谷歌也提供了addr2line/ objdump/ndk-stack工具

一個典型的墓碑文件內容如下

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 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

文件結構

定位工具

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

有需要完整代碼的同學 可以 私信 發送 “底層源碼” 即可 免費獲取

現在發送還可以獲得更多《Android 學習筆記+源碼解析+面試視頻》

JNI 特點:

二進制兼容

● 本地方法庫與同一平臺上所有Java 虛擬機之間實現二進制兼容,即對于給定平臺開發人員只需要維護一種版本的本地方法庫

效率高

為了實現實時系統,JNI 在效率與虛擬機無關性之間進行了優化,以保障高效運行

功能強

● JNI 提供了大量的函數及接口讓本地方法與Java 虛擬機內核相互操作,增強兩者的功能

本地代碼與 Java 虛擬機之間是通過 JNI 函數實現相互操作的;JNI 函數通過接口指針來獲得,本地方法將 JNI 接口指針當作參數來接受;虛擬機保證在從相同的 Java 線程中對本地方法進行多次調用時,傳遞給本地方法的接口指針是相同的,本地方法被不同的 Java 線程調用時,它接受不同的 JNI接口指針

尾述

有需要完整代碼的同學 可以 私信 發送 “底層源碼” 即可 免費獲取

現在發送還可以獲得更多《Android 學習筆記+源碼解析+面試視頻》

技術是無止境的,你需要對自己提交的每一行代碼、使用的每一個工具負責,不斷挖掘其底層原理,才能使自己的技術升華到更高的層面

Android 架構師之路還很漫長,與君共勉

PS:有問題歡迎指正,可以在評論區留下你的建議和感受;

歡迎大家點贊評論,覺得內容可以的話,可以轉發分享一下