Java 哪种方法最终调用JNI_OnLoad

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

我试图弄清楚如何在内部调用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的响应,我的文件跟踪如下:

       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 for
dlopen()
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");
    // ...
}