我在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 lib已附加。我尝试转储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中。
TextClock:
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)
答案 0 :(得分:1)
您可以使用工具链文件夹中的readelf将符号转储到.so文件中。检查是否已导出JNI_OnLoad。 -s(symbols)命令和libs文件夹中.so文件的名称应该这样做。
答案 1 :(得分:1)
在Android的旧版本中,该库直接链接到VM(libdvm.so
链接到libnativehelper.so
,链接到libjavacore.a
。在最近的版本this changed中,始终使用内部本机库加载机制在开始时加载库,因此如果存在,将调用JNI_OnLoad
。
如果我运行adb shell dalvikvm Foo
(其中“Foo”不存在),我会在logcat中看到这一点:
D dalvikvm: Trying to load lib libjavacore.so 0x0
D dalvikvm: Added shared lib libjavacore.so 0x0
D dalvikvm: Trying to load lib libnativehelper.so 0x0
D dalvikvm: Added shared lib libnativehelper.so 0x0
D dalvikvm: No JNI_OnLoad found in libnativehelper.so 0x0, skipping init
所以它加载libjavacore.so
并且显然已找到并运行JNI_OnLoad
(没有新闻是好消息)。它加载了libnativehelper.so
但未找到JNI_OnLoad
,因此它会记录一条消息,告诉您如果您不希望这样做。
如果替换libjavacore.so
中的/system/lib
(在有根设备上)并运行dalvikvm
命令,您应该会在日志文件中看到您的消息,并将消息与我已经在上面展示了。如果重新启动系统,您应该在zygote启动期间看到您的消息,除非某些内容运行基于Dalvik的命令(如am
),否则不会再次显示该消息。