假设 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();
- }
复制代码 |