【发布时间】:2014-02-20 17:30:30
【问题描述】:
我在使用 System.loadLibrary("my_shared_lib"); 加载本机库时遇到问题
问题是这个调用永远不会返回。
这里是上下文:
在我的项目中,我有几个使用 nkd-build 脚本构建的静态库。
为我需要的每个 .a 库使用此 Android.mk 构建它们效果很好:
**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 库上的 nm 命令来检查)。
为了完整,这里是动态加载.so库的.java文件:
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 但仅此而已,应用程序冻结了。
当我的.so 文件中只有一个静态库.a 时,所有这些都可以正常工作。在这种情况下,我可以完美地调用我的本机代码。但是我的项目使用了 8 个 .a 文件,并且我得到了一个冻结的应用程序,因为 loadLibrary 在这种情况下永远不会结束。
loadLibrary 调用有什么问题?你有什么想法吗?
谢谢。
【问题讨论】:
-
你能有一个静态初始化程序或加载类型的函数进入无限循环吗?当“应用程序永远不会返回”时,最终会发生什么?您是否收到“应用程序无响应”对话框? logcat 中的任何内容表明各种线程卡在哪里?您可以尝试用类似使用多个 .a 文件构建的简单库替换真正的库,看看您是否可以缩小问题所在 - 它是有多个文件,还是特别是其中一个文件?
-
您也可以尝试延迟库加载,以便您有机会先连接 ndk-gdb,然后使用调试器观察加载尝试期间发生的情况。
-
我没有显示应用程序没有响应的对话框。我有一个黑屏,logcat 说“启动超时已过期,放弃唤醒锁定!”就在“尝试加载 lib.so”之后。 (知道在应用程序启动时调用了loadLibrary。所以看起来它不是死锁,但loadLibrary似乎在等待一些东西......
标签: java android android-ndk java-native-interface loadlibrary