【问题标题】:java.lang.UnsatisfiedLinkError when loading native library in Android 5.0 [duplicate]在 Android 5.0 中加载本机库时出现 java.lang.UnsatisfiedLinkError [重复]
【发布时间】:2015-05-31 15:41:10
【问题描述】:

我正在通过以下方式加载我的原生库:

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 实例时,我已经指定了本机代码所在的路径,即getDir("native", Context.MODE_PRIVATE)

(我使用NDK release 10生成原生库。当原生代码文件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 位模式以适应该库。 stackoverflow.com/questions/27712921/… 建议安装程序在 APK 中仅检测到 32 位库时会出现这种情况。如果您找不到其他触发该模式的方法,您可能需要在实际 APK 中包含一个占位符 32 位库,以便安装程序查看和响应。最终,你能提供一个 64 位的库吗?
  • @ChrisStratton,感谢您的评论,我需要在 64 位目标上运行我的 32 位库,这是我现在想要实现的目标。
  • 那么我建议你尝试在 apk 中放置一个虚拟的 32 位库。
  • @ChrisStratton,1. 如果我希望系统加载我真正的 32 位库,为什么我需要这个虚拟的 32 位库?我不明白。 2. 我怎样才能创建一个虚拟的 32-lib ??
  • 你已经在stackoverflow.com/questions/28992323/…问过这个问题@不允许转发。

标签: android android-ndk java-native-interface


【解决方案1】:

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

显然,兼容性模式(来源似乎将其称为 ABI 覆盖)通常在安装时设置,安装程序发现只有 32 位(而不是 64 位)库可用。但是在您的情况下,该库在安装时不可见,因此不起作用。

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

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

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

【讨论】:

  • 1. in your case, the library is not visible at install time 为什么? 2. APK 中虚拟 32 位 libt 的路径是什么? /libs/libmyNative.so ??
  • 如果 real 库存在于 apk 中,那么您将完全错误地处理此问题 - 您不应该自己复制本机库,而是让当你调用 System.loadLibrary() 时,系统会自动将其从 apk 中复制出来并自动查找结果。另一方面,如果真正的库毕竟 不在 在 apk 中(可能是因为您打算稍后下载它),那么将虚拟库放在它的 ABI 的传统目录中 - 即,遵循NDK 说明完全正确
  • 谢谢,你是对的。
  • 截至今天,使用带有最新实验性 gradle 的 Android 2.1,使用低于或等于 19 的 compileSdkVersion 会阻止构建 64 位共享库,并且 64 位 Android 上未安装 32 位共享库。这是一团糟,因为不可能同时构建单个 APK 来支持高于和低于 19 的 API,即使共享库在所有 API 版本上都可以正常工作,但使用 20/21+ 编译的共享库将无法正常工作由于更改了 C 库,API 19 及更低版本。一团糟。
  • @3c71 - 不清楚你在说什么(Android 2.1?真的吗?)但无论如何这是错误的地方 - 这个问题作为重复关闭,即这个页面是不应该存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
相关资源
最近更新 更多