美文网首页
Android : UnsatisfiedLinkError

Android : UnsatisfiedLinkError

作者: Nothing_655f | 来源:发表于2020-06-30 18:01 被阅读0次

    在android 上使用 .so作为apk的第三方库的时候,会发生java.lang.UnsatisfiedLinkError:

    09-27 12:17:01.280 D/ListenSoundModel( 3635): Load libxxxjni 
    09-27 12:17:01.292 D/AndroidRuntime( 3635): Shutting down VM 
    ——— beginning of crash 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): FATAL EXCEPTION: main 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): Process: com.xxx.xxx, PID: 3635 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/xxxApp.apk”],nativeLibraryDirectories=[/data/app-lib/xxxApp, /system/lib64, /vendor/lib64]]] couldn’t find “libxxxjni.so” 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): at java.lang.Runtime.loadLibrary0(Runtime.java:972) 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): at java.lang.System.loadLibrary(System.java:1530) 
    … 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): at android.os.Handler.dispatchMessage(Handler.java:102) 
    09-27 12:17:01.293 E/AndroidRuntime( 3635): at android.os.Looper.loop(Looper.java:154)
    
    

    google的变更说明有介绍https://developer.android.com/preview/behavior-changes.html#ndk
    变更出现的这个 UnsatisfiedLinkError 原因是访问设置为公用库的so库
    ......
    可以看看原生的这笔提交修改的。
    android-review.googlesource.com/#/c/209029/

    Android N上对so库加载的搜索路径方式为ld_library_path, runtime path, permit path,不在这个搜索路径下则加载失败。

    从代码层面看,主要是类加载器ClassLoader的相关处理,

    code1: (loadedApk.java getClassLoader()) check sdk version

    // DO NOT SHIP: this is a workaround for apps loading native libraries 
    // provided by 3rd party apps using absolute path instead of corresponding 
    // classloader; see http://b/26954419 for example. 
    if (mApplicationInfo.targetSdkVersion <= 23) { 
    libraryPermittedPath += File.pathSeparator + “/data/app”; 
    }
    

    Code2: (loadedApk.java getClassLoader()) N add a new PermittedPath

    String libraryPermittedPath = mDataDir;
    

    Code3: (native_loader.cpp) use the new namespace rule with search path:

    ld_library_path, runtime path, permit path.
    

    解决方法

    解决方法

    public.libraries.txt Flow

    1、system/core/libnativeloader/native_loader.cpp

    在LibraryNamespaces类的Initialize()会读取这个文件,将so库设置为公共so库。

    static constexpr const char* kPublicNativeLibrariesSystemConfigPathFromRoot = "/etc/public.libraries.txt";
    static constexpr const char* kPublicNativeLibrariesVendorConfig = "/vendor/etc/public.libraries.txt";
      void Initialize() {
        ..................
        std::vector<std::string> sonames;
        ReadConfig(public_native_libraries_system_config, &sonames, &error_msg),
        ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
        public_libraries_ = base::Join(sonames, ':');
        .............
      }
    

    2、在创建一个虚拟机的时候,初始化NativeLoader

    art/runtime/java_vm_ext.cc

    extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
      ................
      // Initialize native loader. This step makes sure we have
      // everything set up before we start using JNI.
      android::InitializeNativeLoader();
      ..............
    }
    

    3、然后进入native_loader,进行初始化

    system/core/libnativeloader/native_loader.cpp

     static LibraryNamespaces* g_namespaces = new LibraryNamespaces;
    void InitializeNativeLoader() {
       g_namespaces->Initialize();
     }
    

    4、Initialize调用LibraryNamespaces类的Initialize完成公共so库

    void Initialize() {
        ..................
        std::vector<std::string> sonames;
        ReadConfig(public_native_libraries_system_config, &sonames, &error_msg),
        ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
        public_libraries_ = base::Join(sonames, ':');
        .............
      }
    

    总结:

    1.Android N 不能直接调用系统的一些私有库了,公用的库都定义在public.libraries.txt里面。
    2.系统应用刚刷机是能够调用system/lib or lib64下的库,但通过install升级该应用时,应用打开会挂。因为升级后permitted_paths就不再包含system/lib or lib64了,所以我们可以将apk要用到的库名称写到public.libraries.txt中去解决快速调试问题。

    参考 https://www.cnblogs.com/zl1991/p/9409462.html

    相关文章

      网友评论

          本文标题:Android : UnsatisfiedLinkError

          本文链接:https://www.haomeiwen.com/subject/mnnxqktx.html