Android 调用System.loadLibrary时未调用onJNILoad
我在JNI_OnLoad中添加了一个print log语句,但是我发现它没有被调用。这是我的JNI_OnLoad方法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还是在
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