Aad*_*hri 12 java java-native-interface
我试图弄清楚如何在内部调用JNI_OnLoad.我最终想出了下面的教程,但它没有说明什么代码部分实际上调用JNI_OnLoad作为内部函数调用.请帮我找到明确调用JNI_OnLoad的链接函数.我观察到System.loadLibrary调用Runtime,它再次调用Classloader.但仍无法找到原生链接.
我对OnLoad.cpp中的那个特别感兴趣(android/platform_frameworks_base/blob/master/services/jni/onload.cpp)
JNI_OnLoad
jint JNI_OnLoad(JavaVM *vm, void *reserved);
The VM calls JNI_OnLoad when the native library is loaded (for example, through
System.loadLibrary). JNI_OnLoad must return the JNI version needed by the native library.
In order to use any of the new JNI functions, a native library must export a JNI_OnLoad function that returns JNI_VERSION_1_2. If the native library does not export a JNI_OnLoad function, the VM assumes that the library only requires JNI version JNI_VERSION_1_1. If the VM does not recognize the version number returned by JNI_OnLoad, the native library cannot be loaded.
Run Code Online (Sandbox Code Playgroud)
编辑:基于@Code Painters响应的文件跟踪如下:
System.loadLibrary("android_servers");
|
|The call System.loadLibrary(name) is effectively equivalent
| to the call
|
V
Runtime.getRuntime().loadLibrary(name)
|
|public static Runtime getRuntime() {
| return currentRuntime;}
|
| // Here, also,Classloader.loadlibrary is called,
| but this is over-ridden (?)
| by the Native function of Runtime.java below
V
/dalvik/vm/native/java_lang_Runtime.cpp (The jni native
implementation of Runtime.java):
/*
* static String nativeLoad(String filename, ClassLoader loader)
*
* Load the specified full path as a dynamic library filled with
* JNI-compatible methods. Returns null on success, or a failure
* message on failure.
*/
static void Dalvik_java_lang_Runtime_nativeLoad{
//
success = dvmLoadNativeCode(fileName, classLoader, &reason);
}
Run Code Online (Sandbox Code Playgroud)
我现在明白Runtime.loadlibrary是用Dalvik_java_lang_Runtime_nativeLoad本机函数重载的,并且不会引发Classloader.loadlibrary.如果我错了,请纠正我.
Cod*_*ers 19
对于Android,您应该查看dalvik/vm/Native.c,它定义了JNI接口.
最相关的功能是这一个:
bool dvmLoadNativeCode(const char* pathName, Object* classLoader);
Run Code Online (Sandbox Code Playgroud)
这是图书馆所在的地方dlopen().最有趣的部分:
vonLoad = dlsym(handle, "JNI_OnLoad");
if (vonLoad == NULL) {
LOGD("No JNI_OnLoad found in %s %p\n", pathName, classLoader);
} else {
/*
* Call JNI_OnLoad. We have to override the current class
* loader, which will always be "null" since the stuff at the
* top of the stack is around Runtime.loadLibrary(). (See
* the comments in the JNI FindClass function.)
*/
OnLoadFunc func = vonLoad;
Object* prevOverride = self->classLoaderOverride;
self->classLoaderOverride = classLoader;
oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
LOGV("+++ calling JNI_OnLoad(%s)\n", pathName);
version = (*func)(gDvm.vmList, NULL);
dvmChangeStatus(self, oldStatus);
self->classLoaderOverride = prevOverride;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,JNI_OnLoad只需dlsym()使用返回的指针进行解析和调用.这段代码的其余部分是检查返回的值JNI_OnLoad,没有什么真正令人兴奋的.
我相信对于其他虚拟机看起来应该看起来几乎相同 - 所以只需要grep dlopen()和dlsym()- 毕竟它只是简单的共享库加载和符号解析.
编辑:说到您提到的确切文件,Android.mk在同一目录中编译并将此文件链接到libandroid_servers共享库.这个库名称的左侧显示了services/java/com/android/server/SystemServer.java.
什么是相关的:
public static void main(String[] args) {
// ...
System.loadLibrary("android_servers");
// ...
}
Run Code Online (Sandbox Code Playgroud)
因此,在Android的系统服务启动的上下文中执行库的加载(以及对JNI_OnLoad()in 的调用onload.cpp).如果您想了解有关系统服务加载方式/时间的更多信息,我建议您使用此演示文稿.