【问题标题】:Android NDK UnsatisfiedLinkError: "dlopen failed: empty/missing DT_HASH"Android NDK UnsatisfiedLinkError: "dlopen failed: empty/missing DT_HASH"
【发布时间】:2015-02-20 21:48:27
【问题描述】:

我正在使用崩溃报告服务跟踪我们的 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)

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

根据崩溃痕迹,任何特定用户似乎都会在一段时间内不断体验到这种情况;我不确定这些用户是否能够正确加载库。有没有人知道什么可能导致这种情况仅在有时发生?我可以通过不同的方式构建 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

【问题讨论】:

  • 您找到原因了吗?我正在构建的本机库也有同样的问题。很少有用户看到它,但有些用户收到由 empty/missing DT_HASH in "libGLESv3.so" (built with --hash-style=gnu?) 引起的 java.lang.UnsatisfiedLinkError

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


【解决方案1】:

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

【讨论】:

  • 无法再访问已提交的应用程序问题,但我同意这似乎是最好的建议。快速谷歌建议这个问题在 2015 年出现飙升,然后逐渐消失,有轶事证据表明 ReLinker 中存在错误。无论如何,如果您作为第三方库开发人员将其设置为“两者”,我认为您已经完成了尽职调查。
【解决方案2】:

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

您是如何构建cpplibrary.so 的?如果您没有手动切换到 gnu 哈希样式,则可能是 NDK 中的错误。

【讨论】:

  • 感谢您的建议。我目前没有在任何地方设置哈希样式。我可以尝试将其显式设置为 sysv,但因为很少有用户遇到它,所以在我们的下一个应用程序发布之前我不会看到结果。我会试试看有没有什么不同。
  • 我也有同样的问题。因为我的问题是第三方 cpplibrary.所以我不能简单地用-Wl,--hash-style=sysv' 构建库。有什么建议吗?
  • 告诉第三方库的作者他们构建错误。如果您想继续使用该库,这是唯一可能的解决方法。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    虽然出了这个问题,但我在Android Studio导入第三方so文件时遇到了这个问题。最后我发现这是因为 Gradle 自动剥离了产品的 'so' 文件,所以禁用这个选项就可以了。

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

    【讨论】:

      【解决方案5】:
      【解决方案6】:

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

      【讨论】:

      • 谢谢,这是个好建议。这是我对这些问题的第一个怀疑,但所有发生崩溃的设备都是我们支持的 armeabi-v7。此外,并非每台设备都出现 100% 的崩溃;我们有一台运行良好的三星 S5,但那是一款崩溃的手机。
      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-03
          • 1970-01-01
          • 1970-01-01
          • 2017-03-21
          • 1970-01-01
          • 1970-01-01
          • 2015-12-27
          • 1970-01-01
          相关资源
          最近更新 更多