有一次我在共享库编译时遇到问题,应用程序崩溃并显示以下跟踪日志:
backtrace:
#00 pc 00000000001938f8 /data/app/com.xxxxx.test-1/lib/arm64/libmyNative.so
#01 pc 0000000000002300 /system/bin/linker64 (__dl__ZN6soinfo12CallFunctionEPKcPFvvE.part.22+80)
#02 pc 000000000000294c /system/bin/linker64 (__dl__ZN6soinfo9CallArrayEPKcPPFvvEmb+232)
#03 pc 0000000000005200 /system/bin/linker64 (__dl__Z9do_dlopenPKciPK17android_dlextinfo+264)
#04 pc 0000000000001cbc /system/bin/linker64 (__dl__ZL10dlopen_extPKciPK17android_dlextinfo+48)
#05 pc 0000000000284bc8 /system/lib64/libart.so (art::JavaVMExt::LoadNativeLibrary(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, art::Handle<art::mirror::ClassLoader>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*)+824)
#06 pc 00000000002c2e2c /system/lib64/libart.so (art::Runtime_nativeLoad(_JNIEnv*, _jclass*, _jstring*, _jobject*, _jstring*)+700)
#07 pc 00000000000b9528 /data/dalvik-cache/arm64/system@framework@boot.oat
从日志中,我们可以了解到这个 libmyNative.so 是如何在第一时间被加载的。
1. boot.oat 不仅负责加载android框架和资源,还负责加载应用程序共享库。
2. boot.oat是一个Java库,它会调用native libart.so来加载native库,Runtime_nativeLoad() -> LoadNativeLibrary()。
3.下面的步骤,如果你之前hook过native library,或者你之前自己从android application动态链接native library,你会更好的理解。自己链接共享库而不是调用 System.loadLibrary() 的一个例子:
void* lib = dlopen("/data/app/com.xxxxx.test-1/lib/arm64/libmyNative.so", RTLD_LAZY);
void* func_ptr = (void*)dlsym(* lib, "JNI_Onload");
所以在 LoadNativeLibrary() 内部,它做了类似的事情。您可以从here 检查 LoadNativeLibrary() 的实现。
在本机库加载期间,还会执行部分初始化代码。如果你知道 .so 文件结构,你就会知道有一个 .init_array 部分,其中包括一些由编译器添加的初始化函数和你在代码中显式声明的全局构造函数。我遇到的崩溃是在编译器添加的 init 函数之一中。
我怀疑的一件事是在 LoadNativeLibrary() 内部,它似乎调用 JNI_Onload(),但据我观察,它没有。因为我试图让JNI_Onload() 直接返回 -1,所以它不会从那里抛出错误消息,而是在我调用 System.loadLibrary() 时抛出错误消息。这是意料之中的。
03-08 18:10:12.311 14797-14797/com.xxxxx.test E/JNI_OnLoad: System.loadLibrary(myNative)
java.lang.UnsatisfiedLinkError: JNI_ERR 从“/data/app/com.xxxxx.test-2/lib/arm64/libmyNative.so”中的 JNI_OnLoad 返回
在 java.lang.Runtime.loadLibrary(Runtime.java:372)
在 java.lang.System.loadLibrary(System.java:988)
在 com.gemalto.tee.taadmin.TaAdmin.init(TaAdmin.java:86)