java.lang.UnsatisfiedLinkError:dlopen 失败:找不到库
Posted
技术标签:
【中文标题】java.lang.UnsatisfiedLinkError:dlopen 失败:找不到库【英文标题】:java.lang.UnsatisfiedLinkError: dlopen failed: library not found 【发布时间】:2019-02-04 04:41:17 【问题描述】:我正在尝试使用 cmake 构建我的 android(本机)项目(从 gradle 实验性插件中迁移它,它曾经可以正常构建和运行)。
我有一些本机代码(将其称为“a”),它使用另一个外部预构建库代码(将其称为“b”),我将两者链接如下: (根据https://developer.android.com/studio/projects/configure-cmake)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++14 -frtti -fno-common -fexceptions")
include_directories(
#a's include files' paths
#b's include files' paths)
file(GLOB_RECURSE A_SOURCES
#a's source files' paths)
add_library(a_lib SHARED $A_SOURCES)
add_library(b_lib SHARED IMPORTED)
set_target_properties(b_lib PROPERTIES IMPORTED_LOCATION "b's .so path")
target_link_libraries(a_lib b_lib)
我完成了编译和链接步骤,android studio 继续在我的设备上安装 APK。但是,启动后,应用程序会在 logcat 中冻结,并显示以下内容:
E/ExceptionHandler: Uncaught Exception java.lang.UnsatisfiedLinkError: dlopen failed: library "libb_lib.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:989)
at java.lang.System.loadLibrary(System.java:1530)
at com.mm.projectname.model.libloadingclassname.<clinit>(libloadingclassname.java:99)
我知道这是因为 b_lib 的 .so 不在 apk 中。我可以在 a 的共享库中看到 b 的符号和 a 的符号。
所以我的问题是我该怎么做
-
将我的预构建 b 的 .so 打包到 apk 中
或阻止系统在 libs 文件夹中查找 b.so,使其仅在 a 的 .so 中查找 b 的符号。
我搜索了很多类似的帖子和问题(例如one 和two),但我什么也做不了。我真的在寻找正确的方法来做到这一点 - 这不会在未来产生问题(比如更改 targetSDKversion)。我还尝试使用最新的 ndk 版本构建预构建的库。
我可能犯了一个非常小的错误,如果有人能指出这一点,我将不胜感激。
提前致谢
【问题讨论】:
把libb_lib.so放到jniLibs里应该就够了。预建库是为什么架构构建的,您正在构建什么架构以及您尝试使用的设备的架构是什么? 存在加载库问题。试试fileTree(dir: 'libs', include: '**/*.so')
。 compile fileTree(dir: 'libs', include: ['.jar','.so'])
@Alex 你的意思是像this吗?我试过了 - 似乎没有解决问题。预建库是为 arm64-v8a、armeabi-v7a、x86 和 x86_64 构建的。我在 armeabi-v7a 架构上试过这个。
我认为如果你像这样放置 libb 应该没问题:src/main/jniLibs/armeabi-v7a/libb_lib.so。你不应该为此在 gradle 中添加任何东西,因为它是从中复制本机库的默认位置。
@Alex 将共享库放入 jniLibs 也不起作用 - 我仍然遇到同样的错误。
【参考方案1】:
-
在应用的
main
目录中创建一个jniLibs
文件夹(例如:/app/src/main
)。
根据架构创建另一个文件夹。
将您的 .so 文件存储在此文件夹中。
【讨论】:
【参考方案2】:有点晚了,但其他人可能会感兴趣(甚至是操作)。
我的情况与操作员相同,我尝试了许多不同的方法。其中之一是尝试使用早期版本的 NDK 编译项目(我认为是 r14b,但我不确定)。我遇到了一个不同的错误,并设法在“无效的 DT_NEEDED 条目”和“缺少 SONAME”部分中找到了 here 中很好描述的问题。此外,这个问题在这个特定的question 中进行了描述,并得到了充分的答复。
如果您无法重新编译您正在使用的共享库以包含 SONAME,就像在我的情况下,您可以执行以下我所做的并设法工作:
在项目树的 jniLibs 文件夹中包含该库,以便将其打包在您的 APK 中,但不要链接到它。 使用here 中描述的任何方法跟踪要合并的函数的符号。 在您的 C++ 代码中创建相应函数的函数指针。 在运行时加载共享库并映射到这些函数。示例代码
标题:
private:
typedef uint32_t (*InitX_t)();
typedef uint32_t (*DoX_t)();
typedef uint32_t (*GetX)(uint32_t, char*);
InitX_t InitX;
DoX_t DoX;
GetX_t GetX;
CPP
void *handle = dlopen("libMyLib.so", RTLD_NOW);
if(handle == nullptr)
__android_log_print(ANDROID_LOG_INFO, "My Class", "Could not load library");
else
__android_log_print(ANDROID_LOG_INFO, "My Class", "Library loaded");
InitX = (InitX_t)dlsym(handle, "InitX_SYMBOL");
ScanX = (ScanX_t)dlsym(handle, "ScanX_SYMBOL");
GetX = (GetX_t)dlsym(handle, "GetX_SYMBOL");
if(ScanX == nullptr || GetX == nullptr || InitX == nullptr)
__android_log_print(ANDROID_LOG_INFO, "My Class", "Could not load functions.");
如果操作正确,您现在应该可以像往常一样使用这些功能了。不过,我知道,如果您是初学者,这并不是最简单的过程。
【讨论】:
以上是关于java.lang.UnsatisfiedLinkError:dlopen 失败:找不到库的主要内容,如果未能解决你的问题,请参考以下文章