使用System.loadLibrary("my_shared_lib");
加载本机库时遇到问题
问题是这个调用永远不会返回。
以下是上下文:
在我的项目中,我使用nkd-build脚本构建了几个静态库。
对于我需要的每个Android.mk
库,使用此.a
构建它们很有效:
**Android.mk used for static libs**
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_static_lib_1
# Include paths
LOCAL_C_INCLUDES := \
$(PATH_TO_INCLUDES1) \
$(PATH_TO_INCLUDES2)
# Sources
LOCAL_SRC_FILES := \
my_source_1.cpp\
my_source_11.cpp
# Target
include $(BUILD_STATIC_LIBRARY)
这些静态库当然只包含本机(C ++)源,以及一些JNI包装器(可从Java源代码调用)。
一旦构建了所有静态库(.a
),我想构建一个包含我需要的所有.so
库的共享库(.a
)。
以下是我用来构建此共享库的Android.mk
:
LOCAL_PATH := $(call my-dir)
#----------
# Static prebuilt libs
#----------
#-- my_static_lib_1
include $(CLEAR_VARS)
LOCAL_MODULE := my_static_lib_1
LOCAL_SRC_FILES := $(PATH_TO_LIBS)/my_static_lib_1.a
include $(PREBUILT_STATIC_LIBRARY)
#-- my_static_lib_2
include $(CLEAR_VARS)
LOCAL_MODULE := my_static_lib_2
LOCAL_SRC_FILES := $(PATH_TO_LIBS)/my_static_lib_2.a
include $(PREBUILT_STATIC_LIBRARY)
#----------
# Building shared lib
#----------
include $(CLEAR_VARS)
LOCAL_MODULE := my_shared_lib
#-- Some of the .a static libs need these libs
LOCAL_LDLIBS := \
-lz\
-llog \
$(PATH_TO_NDK_LIBS)\libstlport_static.a
#-- This variable is used to force libs to be included in the .so
LOCAL_WHOLE_STATIC_LIBRARIES := \
my_static_lib_1\
my_static_lib_2
include $(BUILD_SHARED_LIBRARY)
这为我构建了一个完美的.so
文件,其中包含.a
库中的所有函数(我可以在生成的.so
lib上使用nm命令检查它。)
要完成,这里是动态加载.java
lib的.so
文件:
public class MyClass
{
static {
Log.d("MYLOGS", "Loading...");
System.loadLibrary("my_shared_lib");
Log.d("MYLOGS", "Loaded.");
}
...
}
问题:
当我创建一个新的MyClass实例时,会调用loadLibrary,但它永远不会返回。我可以看到Loading...
日志,但从不看Loaded.
日志。
logCat说Trying to load lib [...].so
,但就是这样,应用冻结了。
当我的.a
文件中只有一个静态库.so
时,所有这一切都正常。在这种情况下,我可以完美地调用我的本机代码。但是我的项目使用了8个.a
文件,我得到了一个冻结的应用程序,因为在这种情况下loadLibrary永远不会结束。
loadLibrary
来电有什么问题?你有什么想法吗?
感谢。
答案 0 :(得分:3)
我发现我的代码出了什么问题。
实际上当loadLibrary加载.so
库时,它会创建.so
中声明的所有全局变量/常量,当然包括.a
中包含的每个.so
库的全局变量/常量。 {1}}。
其中一些全局是通过执行某些代码的构造函数构建的。
我发现在我的.a
libs架构中,这段代码在某些时候陷入僵局,因为它被称为太早(某些需要的东西尚未存在)。我没想到会在loadLibrary
时间调用它。
因此,如果这可以帮助任何人:请记住loadLibrary
涉及创建您尝试加载的.so
库中包含的所有全局对象。
不知道这是我的错误。
答案 1 :(得分:1)
通常,在构建共享库(.so)时,会使用某种编译器选项(如-fPIC)生成与位置无关的代码。另一方面,当您构建静态库(.a)时,不使用此类选项。即使将静态库打包到共享库中,静态库中的二进制代码也不是与位置无关的。这就是loadLibrary()失败的原因,我想。
如果我是你,我会避免将静态库打包到共享库中,而是使用-fPIC或类似的东西编译所有C ++文件。