Android 调用System.loadLibrary时未调用onJNILoad

Android 调用System.loadLibrary时未调用onJNILoad,android,c,android-ndk,java-native-interface,dalvik,Android,C,Android Ndk,Java Native Interface,Dalvik,我在JNI_OnLoad中添加了一个print log语句,但是我发现它没有被调用。这是我的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还是在

我在JNI_OnLoad中添加了一个print log语句,但是我发现它没有被调用。这是我的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中声明sth告诉系统在哪里可以找到JNI_OnLoad方法?现在,我只把它放在许多.cpp文件中的一个

所以附加了lib。我尝试转储so文件,并且我确信JNI_OnLoad方法已导出。

实际上,我正在尝试从android源代码(libcorejava.so)移植一个库。为了避免类路径冲突,我已经更改了类路径

下面是声明JNI_OnLoad的文件: 我已经将签名更改为上述签名,以匹配标准签名

编辑: 我发现android source没有通过System.loadLibrary加载它!它说libcorejava是用来实现System.loadLibrary的,所以我们不能使用System.loadLibrary来加载它。但在我的情况下,这不应该是一个问题,因为我只需要部分功能(ICU相关)

编辑2:
原来是因为库的名称冲突! 但libjavacore似乎需要其他库。是否有任何工具可以列出我缺少的依赖项

java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: XXX
编辑3:
TextClock是一种用于显示时间的新api。它只存在于4.2+api up中。我正在尝试将其向后移植,以便旧sdk可以使用它。它依赖于驻留在libjavacore中的ICU库。因此,我修改了Android.mk文件,以确保libjavacore只包含与icu相关的源文件,并且最终编译的So文件包含在我的apk中

文本时钟:

它现在可以在最初支持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)

您可以使用工具链文件夹中的readelf转储.so文件中的符号。检查JNI_OnLoad是否已导出。-s(symbols)命令和libs文件夹中.so文件的名称应该可以完成此操作。

在旧版本的Android中,库直接链接到VM(
libdvm.so
链接到
libnativehelper.so
链接到
libjavacore.a
)。在最近的版本中,使用内部本机库加载机制始终在启动时加载库,因此如果存在,将调用
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\u OnLoad
,因此它记录了一条消息告诉您这样做,以防您期望其他情况


如果替换
/system/lib
中的
libjavacore.so
(在根设备上),并运行
dalvikvm
命令,您应该会在日志文件中看到您的消息,与上面显示的消息混合在一起。如果重新启动系统,您应该在zygote启动期间看到消息,除非有东西运行基于Dalvik的命令(如
am
)。

将其放入众多cpp文件中即可。我不知道问题是什么,但我很确定这不是原因。我唯一想到的是你忘了在函数前面加上外部“C”。我没有。为什么需要它?我试图更改为extern“C”JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM*vm,void*reserved){,但仍然是一样的……当成为应用程序的进程从zygote中分叉时,您可能面临着与已加载的工厂版本的冲突——它可能认为库已加载,但可能什么也不做。Logcat可能会澄清。或者获取一个shell作为应用程序uid,并查看它的/proc/pid###/maps或转储它从Java代码。您可能需要为库命名其他名称,但请注意函数名冲突!是的…如果在调用exec()之前替换或重写原始库路径函数从头开始初始化。但我怀疑海报是在尝试将它们自己的.apk打包并显式加载,这可能不起作用,因为系统版本在它们尝试将它们加载到后代apk进程之前已经加载到父合子中。啊。如果VM认为它是同一个库,那么在logcat中应该有一条“已经加载”的消息;如果没有,那么我希望
JNI_OnLoad
能够正常工作(新方法取代旧方法,因为它们使用显式注册)。您先前提出的重命名共享库的建议可能会解决问题。@fadden很抱歉,我将移植库而不是替换。因此重命名很有效。谢谢大家。
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