OpenJDK9 Hotspot java 虚拟机入口

 2019-12-22 10:26  阅读(1029)
文章分类:JVM

假设 openjdk 源代码目录为 jdk9dev

main函数

main 函数在 jdk9dev/jdk/src/java.base/share/native/launcher/main.c,它处理完命令行参数后跳转到 JLI_Launch 函数

int main(int argc, char** argv) {
            // 处理命令行选项
            ...

            return JLI_Launch(margc, margv,
                       sizeof(const_jargs) / sizeof(char *), const_jargs,
                       appclassc, const_appclasspath,
                       VERSION_STRING,
                       DOT_VERSION,
                       (const_progname != NULL) ? const_progname : *margv,
                       (const_launcher != NULL) ? const_launcher : *margv,
                       HAS_JAVA_ARGS,
                       const_cpwildcard, const_javaw, const_ergo_class);
        }

JLI_Launch

JLI_Launch 函数在 jdk9dev/jdk/src/java.base/share/native/libjli/java.c,
它调用 LoadJavaVM 加载 libjvm.dylib , 这个 libjvm.dylib 就是 hotspot 编译的产出!

int JLI_Launch(...) {
            ...

            if (!LoadJavaVM(jvmpath, &ifn)) {
                return (6);
            }

            ...

            return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
        }

LoadJavaVM

在 mac osx 系统下 LoadJavaVM 在 jdk9dev/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c

jboolean LoadJavaVM(const char* jvmpath, InvocationFunctions* ifn) {
        ...
    #ifndef STATIC_BUILD
        libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
    #else
        libjvm = dlopen(NULL, RTLD_FIRST);
    #endif
        ifn->CreateJavaVM = (CreateJavaVM_t)
           dlsym(libjvm, "JNI_CreateJavaVM");
        if (ifn->CreateJavaVM == NULL) {
            JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
            return JNI_FALSE;
        }
        ...
    }

使用 dlopen 加载动态库并获取 JNI_CreateJavaVM 函数入口地址

JVMInit

在 mac osx 系统下 JVMInit 在jdk9dev/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c

熟悉 objc 的同学,对下面的代码应该会感到很亲切:

int JVMInit(InvocationFunctions* ifn, jlong threadStackSize, ...) {
        ...
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        {
            JavaLaunchHelper* launcher = [[[JavaLaunchHelper alloc] init] autorelease];
            [launcher performSelectorOnMainThread:@selector(launchJava:)
                                       withObject:[NSValue valueWithPointer:(void*)&args]
                                    waitUntilDone:YES];
            rslt = [launcher getReturnValue];
        }
        [pool drain];
        return rslt;
        ...
    }

创建 JavaLaunchHelper 对象,并将控制流跳转到 launchJava

@implementation JavaLauncherHelper
    -(int) launchJava:(NSValue*) argsValue {
        _returValue = JavaMain([argsValue pointerValue]);
    }
    @end

呵呵,在 objc 环境短暂停留后控制留又回到 c/c++ 的世界-JavaMain

JavaMain

JavaMain 函数在 jdk9dev/jdk/src/java.base/share/native/libjli/java.c,
在 JavaMain 函数中 会初始化 java 虚拟机,查找 main class,获取 main class 的 main 方法,并开始执行 java 字节码

int JNICALL JavaMain(void* _args) {
        ...
        // 初始化 jvm
        if (!InitializeJVM(&vm, &env, &ifn)) {
            ...
        }

        ...
        // 加载 main class
        mainClass = LoadMainClass(env, mode, what);

        ...
        // 获取 main 方法
        mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
                                           "([Ljava/lang/String;)V");

        ...
        // 调用 main 方法
        (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);

        LEAVE();    
    }
点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> OpenJDK9 Hotspot java 虚拟机入口

相关推荐