在我的项目中,我需要加载三个不同的共享库,其中第三个(主要的)依赖于前两个。为简单起见,前两个应命名为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.
答案 0 :(得分:1)
是的,明确加载A,B和C是在Android中工作的正确方法。另一种方法是使用 crazy linker ,这是自NDK r9以来支持的。
在任何情况下,为项目中使用的库选择特殊名称非常重要,因此不会偶然使用系统库。例如。 Android设备在libcrypto.so
中有libssl.so
和/system/lib
,但许多应用需要更多这些应用的更新版本。
更新:来自NDK的疯狂链接器为removed,但可以找到in chromium project(latest change: June 2017)。