调用System.loadLibrary时没有调用onJNILoad

时间:2013-12-13 06:54:58

标签: android c android-ndk java-native-interface dalvik

我在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)

2 个答案:

答案 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),否则不会再次显示该消息。