使用System.loadLibrary调用加载共享库永远不会返回

时间:2014-02-20 17:30:30

标签: java android android-ndk java-native-interface loadlibrary

使用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来电有什么问题?你有什么想法吗?

感谢。

2 个答案:

答案 0 :(得分:3)

我发现我的代码出了什么问题。

实际上当loadLibrary加载.so库时,它会创建.so中声明的所有全局变量/常量,当然包括.a中包含的每个.so库的全局变量/常量。 {1}}。

其中一些全局是通过执行某些代码的构造函数构建的。 我发现在我的.a libs架构中,这段代码在某些时候陷入僵局,因为它被称为太早(某些需要的东西尚未存在)。我没想到会在loadLibrary时间调用它。

因此,如果这可以帮助任何人:请记住loadLibrary涉及创建您尝试加载的.so库中包含的所有全局对象。

不知道这是我的错误。

答案 1 :(得分:1)

通常,在构建共享库(.so)时,会使用某种编译器选项(如-fPIC)生成与位置无关的代码。另一方面,当您构建静态库(.a)时,不使用此类选项。即使将静态库打包到共享库中,静态库中的二进制代码也不是与位置无关的。这就是loadLibrary()失败的原因,我想。

如果我是你,我会避免将静态库打包到共享库中,而是使用-fPIC或类似的东西编译所有C ++文件。