Android NDK / JNI:loadLibrary失败,具有相关的共享库

时间:2014-07-27 10:29:42

标签: android android-ndk shared-libraries unsatisfiedlinkerror

在我的项目中,我需要加载三个不同的共享库,其中第三个(主要的)依赖于前两个。为简单起见,前两个应命名为A& B而第三个C.

库A和B是大型库,根本不通过JNI进行交互,只是现有库到android的端口。

通过设置我的第三个库的android.mk,我已经设置了这样一个没有问题的系统:

include $(CLEAR_VARS)

LOCAL_PATH := $(MY_LOCAL_PATH)

LOCAL_MODULE    := C
LOCAL_SRC_FILES := <source files>

LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)/libA/
LOCAL_C_INCLUDES += $(MY_LOCAL_PATH)/libB/
LOCAL_SHARED_LIBRARIES := A
LOCAL_SHARED_LIBRARIES += B
LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

通过java加载此库时我使用过:

static{
    System.loadLibrary("C");
}

取得了很大的成功。

这个系统可以在我的设备上运行,除了我的一个beta测试人员,他们的堆栈跟踪中收到了UnsatisfiedLinkError:

java.lang.ExceptionInitializerError
  at <source>:<line>
  at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1892]: 1909 could not load needed library 'libA.so' for 'libC.so' (load_library[1094]: Library 'libA.so' not found)
  at java.lang.Runtime.loadLibrary(Runtime.java:370)
  at java.lang.System.loadLibrary(System.java:535)
  at <source>:<line>
...

将我的代码更改为:

static{
    System.loadLibrary("A");
    System.loadLibrary("B");
    System.loadLibrary("C");
}

似乎解决了该测试人员的问题。

问题的测试人员在armeabi-v7a(与我的设备相同)上运行了三星Galaxy SIII和Android 4.1.2(由我的本机代码支持)。

鉴于单个“加载C”适用于除了那个测试人员以外的所有人,是测试人员设备的问题还是“正确”的方式来显式加载所有三个库?为什么它只会因为那台设备而失败。

LogCat表示单个“加载C”与明确加载:

07-26 23:23:29.333: D/App(13753): Loading core...
07-26 23:23:29.333: D/dalvikvm(13753): Trying to load lib /data/app-lib/com.foo.bar.app-2/libC.so 0x41bfd598
07-26 23:23:29.333: D/dalvikvm(13753): Added shared lib /data/app-lib/com.foo.bar.app-2/libC.so 0x41bfd598
07-26 23:23:29.338: D/App(13753): Core loaded.

vs loading all:

07-26 23:17:50.193: D/App(12714): Loading core...
07-26 23:17:50.198: D/dalvikvm(12714): Trying to load lib /data/app-lib/com.foo.bar.app-1/libA.so 0x41bfaf20
07-26 23:17:50.198: D/dalvikvm(12714): Added shared lib /data/app-lib/com.foo.bar.app-1/libA.so 0x41bfaf20
07-26 23:17:50.203: D/dalvikvm(12714): No JNI_OnLoad found in /data/app-lib/com.foo.bar.app-1/libA.so 0x41bfaf20, skipping init
07-26 23:17:50.208: D/dalvikvm(12714): Trying to load lib /data/app-lib/com.foo.bar.app-1/libB.so 0x41bfaf20
07-26 23:17:50.208: D/dalvikvm(12714): Added shared lib /data/app-lib/com.foo.bar.app-1/libB.so 0x41bfaf20
07-26 23:17:50.208: D/dalvikvm(12714): No JNI_OnLoad found in /data/app-lib/com.foo.bar.app-1/libB.so 0x41bfaf20, skipping init
07-26 23:17:50.208: D/dalvikvm(12714): Trying to load lib /data/app-lib/com.foo.bar.app-1/libC.so 0x41bfaf20
07-26 23:17:50.208: D/dalvikvm(12714): Added shared lib /data/app-lib/com.foo.bar.app-1/libC.so 0x41bfaf20
07-26 23:17:50.208: D/App(12714): Core loaded.

1 个答案:

答案 0 :(得分:1)

是的,明确加载A,B和C是在Android中工作的正确方法。另一种方法是使用 crazy linker ,这是自NDK r9以来支持的。

在任何情况下,为项目中使用的库选择特殊名称非常重要,因此不会偶然使用系统库。例如。 Android设备在libcrypto.so中有libssl.so/system/lib,但许多应用需要更多这些应用的更新版本。

更新:来自NDK的疯狂链接器为removed,但可以找到in chromium projectlatest change: June 2017)。