【发布时间】:2013-12-13 06:54:57
【问题描述】:
我在 JNI_OnLoad 中添加了一条打印日志语句,但我发现它没有被调用。这是我的 JNI_OnLoad 方法。
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
__android_log_print(ANDROID_LOG_INFO, __FUNCTION__, "onLoad");
// some init code
}
我是否需要在特定文件中声明 JNI_OnLoad 或在 Android.MK 中声明某事告诉系统在哪里可以找到 JNI_OnLoad 方法?现在我只是放入众多 .cpp 文件之一。
已附加已编译的 .so 库。我尝试转储 so 文件,我确定 JNI_OnLoad 方法已导出。 https://docs.google.com/file/d/0B089WeEZXTb3ZjZiQllaYThuUUk/edit
实际上,我正在尝试从 android 源 (libcorejava.so) 移植一个库。为了避免类路径冲突,我已经更改了类路径。
这里是声明 JNI_OnLoad 的文件: https://android.googlesource.com/platform/libcore/+/master/luni/src/main/native/Register.cpp 我已经将签名更改为上述签名以匹配标准签名
编辑: 我发现android源没有通过System.loadLibrary加载它!它说libcorejava是用来实现System.loadLibrary的,所以我们不能使用System.loadLibrary来加载它。但就我而言,这应该不是问题,因为我只需要部分功能(ICU 相关)。
https://android.googlesource.com/platform/dalvik/+/master/vm/Init.cpp
// Most JNI libraries can just use System.loadLibrary, but you can't
// if you're the library that implements System.loadLibrary!
loadJniLibrary("javacore");
loadJniLibrary("nativehelper");
编辑 2:
原来是因为库的名字冲突!
但似乎 libjavacore 需要其他库。有什么工具可以列出我缺少的依赖项吗?
java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: XXX
编辑 3:
TextClock 是一个新的显示时间的 api。它只存在于 4.2+ api 上。我正在尝试向后移植它,以便旧的 sdk 可以使用它。它依赖于位于 libjavacore 中的 ICU 库。所以我修改了 Android.mk 文件,以确保 libjavacore 只包含 icu 相关的源文件,并且最终编译的 so 文件包含在我的 apk 中。
文本时钟:
http://developer.android.com/reference/android/widget/TextClock.html
它现在可以在最初支持 TextClock 的手机中使用,但不能在旧设备中使用。这是异常日志。我认为这是因为 libjavacore 是 ICU 库的包装器。除了包装器,我还需要移植 ICU 库。但我要放弃了,因为 ICU 图书馆的规模很大,而且似乎不值得……
12-13 14:07:54.859: E/AndroidRuntime(2091): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1306]: 36 cannot locate '_ZN6icu_516Locale14createFromNameEPKc'...
12-13 14:07:54.859: E/AndroidRuntime(2091): at java.lang.Runtime.loadLibrary(Runtime.java:370)
12-13 14:07:54.859: E/AndroidRuntime(2091): at java.lang.System.loadLibrary(System.java:535)
12-13 14:07:54.859: E/AndroidRuntime(2091): at com.example.time.MainActivity.onCreate(MainActivity.java:20)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.Activity.performCreate(Activity.java:5008)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.ActivityThread.access$600(ActivityThread.java:130)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.os.Handler.dispatchMessage(Handler.java:99)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.os.Looper.loop(Looper.java:137)
12-13 14:07:54.859: E/AndroidRuntime(2091): at android.app.ActivityThread.main(ActivityThread.java:4745)
12-13 14:07:54.859: E/AndroidRuntime(2091): at java.lang.reflect.Method.invokeNative(Native Method)
12-13 14:07:54.859: E/AndroidRuntime(2091): at java.lang.reflect.Method.invoke(Method.java:511)
12-13 14:07:54.859: E/AndroidRuntime(2091): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
12-13 14:07:54.859: E/AndroidRuntime(2091): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
12-13 14:07:54.859: E/AndroidRuntime(2091): at dalvik.system.NativeStart.main(Native Method)
【问题讨论】:
-
将其放入众多 cpp 文件之一即可。我不知道问题是什么,但我很确定这不是原因。我唯一想到的是你忘了在函数前加上 extern "C"。
-
是的,我没有。为什么需要它?
-
我尝试改成 extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {,但还是一样...
-
当成为您的应用程序的进程从 zygote 分叉时,您可能正面临与继承的工厂版本的冲突已经加载 - 它可能什么都不做库已经加载。 Logcat 可能会澄清。或者获取一个 shell 作为应用程序 uid 并查看它的 /proc/pid##/maps 或从 Java 代码中转储它。您可能需要为您的库命名其他名称,但请注意函数名称冲突!
标签: android c android-ndk java-native-interface dalvik