java.lang.UnsatisfiedLinkError 在 Android 5.0 中加载本机库时

java.lang.UnsatisfiedLinkError when loading native library in Android 5.0

我正在通过以下方式加载我的本地库:

try {
       System.loadLibrary("myNative");
} catch (UnsatisfiedLinkError e) {
       //java.lang.UnsatisfiedLinkError here
       System.load("/data/data/com.my.app/app_native/libmyNative.so");
}

以上代码最终打包成Jar文件。

在另一个项目中,我用 DexClassLoader:

加载上面的 Jar
DexClassLoader dexClassLoader = new DexClassLoader(jarPath,
                    optJarPath,
                    getDir("native", Context.MODE_PRIVATE),
                    getClassLoader());

注意,在构造这个dexClassLoader实例时,我指定了path本地代码所在的路径,即getDir("native", Context.MODE_PRIVATE).

(我是用NDK release 10生成native库,生成native代码文件libmyNative.so时,我的java代码(打包到最终 Jar)检查 CPU 架构类型并将正确的复制到 getDir("native", Context.MODE_PRIVATE)。)

以上代码在 Android 5.0 Lollipop 以外的其他设备上运行良好。当 运行 在 Android 5.0 Lollipop 设备上时,我不断收到以下错误:

java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.my.app/app_native/libmyNative.so" is 32-bit instead of 64-bit
at java.lang.Runtime.load(Runtime.java:331)
at java.lang.System.load(System.java:982)

如何解决这个问题?

您似乎试图在 64 位目标上使用 32 位库。如果您不能提供 64 位的,则必须说服 Android 回退到 32 位模式以容纳该库。

显然,兼容模式(来源似乎称其为 ABI 覆盖)通常在安装时设置,安装程序发现只有 32 位(而不是 64 位)库可用。但在你的情况下,库在安装时是不可见的,所以这是行不通的。

如果您在 apk 中放置一个最符合 64 位设备需求的 "dummy" 32 位库,那么系统有望将您的应用配置为 运行 in 32 -位兼容模式,以便稍后加载您真正的 32 位库将实际工作。

我不知道 32 位库是否需要是一个真实的库还是一个具有正确位置和合理名称的空文件,但是来自 ndk 示例文件夹的 libhello-jni.so 应该可以。您不需要任何相应的 java 代码,只需要一个安装程序可以发现的本机库(但是,将其作为测试调用可能不是一个坏主意)。

可能有一些其他方式来触发它,例如清单中的内容(尽管文档中未提及任何内容)。我不太可能怀疑 运行 时间的任何措施都会起作用,因为这种模式可能已经在您的任何代码 运行 之前被牢固地设置(看起来您实际上可能最终得到在这样的系统上有两个 zygote 运行ning 实例,一个 64 位,另一个 32 位,其想法是应用程序由认为合适的任何一个启动。