【问题标题】:android load library failedandroid加载库失败
【发布时间】:2015-12-27 21:31:47
【问题描述】:

当我使用System.loadLibrary() 加载我的so 文件时,它很少会失败并且Logcat 会显示

Cannot load library: reloc_library[1286]: 121 cannot locate '__cxa_atexit'
java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1285]:   169 cannot locate '__cxa_atexit'...
at java.lang.Runtime.loadLibrary(Runtime.java:370)
at java.lang.System.loadLibrary(System.java:535)

在网上搜索后,我没有找到任何关于

的信息
cannot locate '__cxa_atexit'

(尤其是关键字__cxa_atexit)。为什么找不到这个功能?这个函数似乎在 libc.so 中。我在本机代码中不使用 C++,只使用 C。我的 NDK 版本是 android-ndk-r10e。我认为“找不到 __cxa_atexit”可能是一个相对的线索。

大多数时候(可能是应用程序启动数十亿次),它可以正常工作,但很少会像上面那样崩溃。换句话说,我不能让它在我的测试手机上崩溃,但是,它很少会在某些用户的手机上崩溃。

这个问题可能和another problem一样。

更新

发生此崩溃的大多数手机是 android 4.0.3 和 android 4.0.4。这两个版本都是 API-15。

更新

看了一些Android的源码,发现这个问题可能和dlopen有关。错误消息“无法加载库:reloc_library...”来自在运行时被劫持的函数 dlopen。跟踪是runtime dlopen -> find_library -> init_library -> link_image -> reloc_library。

也许当它解析我的so文件中的符号时,它发现“__cxa_atexit”是未定义的。然后它在加载的符号中查找,但什么也没找到。 (为什么找不到 __cxa_atexit ?)最后运行到第 1285 行,代码如下:

DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name);

我对链接器一无所知。谁能解释或猜测为什么找不到 __cxa_atexit ?是安卓的bug吗?

更新

它在所有 Android 版本上崩溃,不仅是 4.0.3 和 4.0.4。

4.0.3 和 4.0.4 上的错误消息是

java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: 121 cannot locate '__cxa_atexit'

如上所述。

在 4.0.3 和 4.0.4 上加载其他的时候,它是

cannot locate 'strcpy'

4.2.2 上的错误信息是

java.lang.UnsatisfiedLinkError: Cannot load library: load_library(linker.cpp:767): can't read file /mnt/asec/app-name-1/lib/libname.so: I/O error

【问题讨论】:

  • 它们不是同一个问题。正如你提到的,我也使用“System.loadlibrary()”。如果失败,我将从apk中解压缩一个so文件,然后重新加载它。大多数时候,它可以正常工作,但有时会崩溃。换句话说,我不能让它在我自己的手机上崩溃,但是,它会在使用我的应用程序的其他用户上崩溃。
  • @KishuDroid 他们不是类似的问题。我的应用可以在大多数手机上正常运行,不会出现其他错误和崩溃。
  • 我从来没有遇到过这个问题,但是很有可能某些4.0.x设备上的native loader不够稳定。当库的 armeabiarmeabi-v7a 变体都可用时,该加载程序中的一个错误自欺欺人。无论如何,一种解决方法是在 System.loadLibrary("main") 周围添加 try … catch 并重试。另一种治疗方法 - 在 main. 之前显式调用 System.loadLibrary("c")

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


【解决方案1】:

首先,请确保您调用了 System.loadLibrary(),如下所示:

public class MainActivity extends Activity {
    static {
        System.loadLibrary("main")
    }
    ...
}

那么,根据the second answer in this post, 问题在于在您的本机库中静态加载的一些外部依赖项。他们只挂在 Android 4.0 上,并且在 4.2 及更高版本上运行良好。所以你应该检查你的 so 文件。

我只是把他的答案放在这里:

如果您有问题,请在您的库的 JNI_onLoad 中添加一个 __android_log_print(如果您有的话)。如果没有被调用,请检查所有可以静态调用的函数(注意,有些可能隐藏在宏后面)并尝试删除它们以查看是否能够加载库

【讨论】:

  • 如果我像你一样调用 System.loadLibrary() 它将很少崩溃。我尝试了另一种方式。当我构造单个实例时,我调用 System.loadLibrary(),如果失败,我从 apk 文件中解压缩一个 so 文件,然后调用 System.load()。然而,它没有帮助。顺便说一句,它在许多版本的 android os(4.0.3 - 5.1) 上崩溃,在 4.0.3 和 4.0.4 上比较容易。
  • 我更新了这个问题。关于 __cxa_atexit 的任何想法?
  • 由于大多数情况下都可以加载库并且很少崩溃,因此建议您调试so库(如果您有源代码),so库中加载的一些外部依赖项可能会导致问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-01
相关资源
最近更新 更多