Java 哪种方法最终调用JNI_OnLoad
我试图弄清楚如何在内部调用JNI_OnLoad。我最终理解了下面的教程,但它并没有说明代码部分实际上是如何将JNI_OnLoad作为内部函数调用的。请帮助我找到显式调用JNI_OnLoad的link函数。我观察到System.loadLibrary调用Runtime,而Runtime再次调用Classloader。但是仍然找不到本机链接 我对OnLoad.cpp(android/platform\u frameworks\u base/blob/master/services/jni/OnLoad.cpp)中的一个特别感兴趣 编辑:根据@Code Painters的响应,我的文件跟踪如下:Java 哪种方法最终调用JNI_OnLoad,java,java-native-interface,Java,Java Native Interface,我试图弄清楚如何在内部调用JNI_OnLoad。我最终理解了下面的教程,但它并没有说明代码部分实际上是如何将JNI_OnLoad作为内部函数调用的。请帮助我找到显式调用JNI_OnLoad的link函数。我观察到System.loadLibrary调用Runtime,而Runtime再次调用Classloader。但是仍然找不到本机链接 我对OnLoad.cpp(android/platform\u frameworks\u base/blob/master/services/jni/OnLoa
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);
}
我现在了解到Runtime.loadlibrary被Dalvik_java_lang_Runtime_nativeLoad本机函数重载,而Classloader.loadlibrary不会被调用。如果我错了,请纠正我。对于Android,您应该查看定义JNI接口的 最相关的功能是: 这里是库的所在地,库是
dlopen()
-ed。最有趣的部分是:
如您所见,JNI_OnLoad
只需使用dlsym()
解析,并使用返回的指针调用。代码部分的其余部分是检查由JNI\u OnLoad
返回的值,没有什么真正令人兴奋的
我相信对于其他虚拟机来说应该是一样的-所以只需grep fordlopen()
和dlsym()
-毕竟它只是简单的共享库加载和符号解析
Edit:说到您提到的确切文件,Android.mk
在同一目录中编译并将该文件链接到libandroid\u服务器
共享库。搜索此库名称将显示
相关内容:
因此,库的加载(因此在
OnLoad.cpp
中调用JNI_OnLoad()
)是在Android系统服务启动的上下文中执行的。如果您想了解更多关于如何/何时加载系统服务的信息,我建议。我有点不明白问题是什么。您是否在源代码中寻找调用JNI_OnLoad()的位置?在什么虚拟机实现中?是的。当我深挖寻找同样的东西时,我终于迷路了。。。尤其是在Android场景中。我不会称之为重载-Runtime.loadLibrary()
将调用委托给私有静态本机布尔nativeLoad(字符串文件名,类加载器)代码>,它是本地声明的,是在C或C++中实现的每一个本地方法。这就是JNI的工作原理-您使用native
关键字在Java中声明(并且仅声明)一个方法,并在C/C++中实现它。除此之外,您列出的调用链看起来是正确的。此外,没有ClassLoader.loadLibrary()
-有loadLibraryWithClassLoader()
和loadLibraryWithPath()
方法,但据我所知,这两种方法在ClassLoader
中都是空的,而且没有ClassLoader
子类实现过它们。对不起!我想具体了解它与System.loadLibrary的实现关系。正如我所提到的,我引用的JNI_加载在OnLoad.cpp中(在问题中链接),但这正是我向您指出的。loadLibrary()是用C实现的,上面引用的部分负责在加载库时调用JNI_OnLoad。你的问题有点让人困惑——你问的是“显式调用JNI_OnLoad的函数”。第一个链接已经失效。
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);
}
bool dvmLoadNativeCode(const char* pathName, Object* classLoader);
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;
public static void main(String[] args) {
// ...
System.loadLibrary("android_servers");
// ...
}