Android NDK UnsatisfiedLinkError:" dlopen失败:空/丢失DT_HASH"

时间:2015-02-20 21:48:27

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

我正在使用崩溃报告服务跟踪我们的Android应用程序(使用NDK加载C ++库)的崩溃。少数用户遇到以下崩溃:

java.lang.UnsatisfiedLinkError: dlopen failed: empty/missing DT_HASH in "cpplibrary.so" (built with --hash-style=gnu?)
   at java.lang.Runtime.loadLibrary(Runtime.java:365)
   at java.lang.System.loadLibrary(System.java:526)

我可以在互联网上找到的这个错误提及(例如这个Google Groups post)讨论了构建lib的问题,这会导致每次运行应用程序时都会出现此错误。几乎没有关于为什么偶尔会发生这种情况的信息。 This post是我能找到的最接近的。

根据崩溃痕迹,看起来任何特定的用户都会经历这种不断的延伸;我不确定这些用户是否能够正确加载lib。有没有人对有时可能导致这种情况发生的想法有所了解?我可以以不同的方式进行NDK构建以试图阻止它吗?

谢谢!

编辑:This post提到了两种有条件地获取此类错误的方法;我会照顾他们。

Edit2:构建文件: Android.mk(摘录):

include $(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_C_INCLUDES := <Source Path>...
LOCAL_CFLAGS := -DANDROID -Wall
LOCAL_CPPFLAGS := -DENABLE_SDK_DEBUGGING=1 -DENABLE_SDK_LOGGING=1
LOCAL_MODULE := cpplibrary
LOCAL_SRC_FILES := <Source Files> / ...

LOCAL_LDLIBS    := -llog -landroid
LOCAL_STATIC_LIBRARIES := cpplibrary
include $(BUILD_SHARED_LIBRARY)

Application.mk:

APP_STL := stlport_static
APP_CFLAGS += -std=c++11

8 个答案:

答案 0 :(得分:3)

您尝试加载的库很可能是使用-Wl,--hash-style=gnu构建的。 Android直到最近才支持此功能(即使在L中也不支持)。您需要使用-Wl,--hash-style=sysv构建库。

你是如何建立cpplibrary.so的?如果您没有做任何事情来手动切换到gnu哈希样式,那么它可能是NDK中的一个错误。

答案 1 :(得分:1)

如果您是第三方建筑.so库供他人使用,则设置-Wl,--hash-style=both似乎是最好的主意。这使您可以更快地加载Gnu样式的哈希值和SysV哈希值的向后兼容性。

答案 2 :(得分:1)

答案 3 :(得分:1)

我在使用Android Cmake时遇到了这个问题,并且已经设置 -DANDROID_PLATFORM=23 根据{{​​3}},GNU哈希样式可从API 23获得,并且由于ANDROID_PLATFORM设置为23,因此标记--hash-style=gnu被自动设置。

我已经通过降低-DANDROID_PLATFORM=21来解决此问题,然后将该标志设置为标志--hash-style=both

答案 4 :(得分:0)

这可能是由于目标设备的不同构造造成的。您是否能够从崩溃报告中收集设备供应商/型号信息? 不确定,但我猜你需要在多个拱门(armeabi,armeabi-v7,neon)中编译本地库,以克服这种不可能性。

答案 5 :(得分:0)

要查看它是否是哈希样式问题,您可以运行readelf -d cpplibrary.so并查找GNU_HASH部分。如果有一个--hash-style = sysv应该解决问题。

答案 6 :(得分:0)

尽管出于这个问题,我在Android Studio导入第三方so文件中遇到了这个问题。最终,我发现这是因为Gradle自动剥离了产品的“ so”文件,因此禁用此选项即可。

android {
	........
    packagingOptions{
        doNotStrip "*/armeabi-v7a/*.so"
    }
   .......
}

答案 7 :(得分:0)

如果有人使用 this project template 为 Flutter 构建 Rust 库,将 makefile 中的相应行更改为 ANDROID_ARMV7_LINKER=$(ANDROID_NDK_HOME)/toolchains/llvm/prebuilt/$(OS_NAME)-x86_64/bin/armv7a-linux-androideabi22-clang 会有所帮助。