OpenJDK源码分析(2)
找到jvm.dll之后呢?——加载。
也就是获取到应该加载的jvmPath之后,java.c接下来执行到263行:
if (!LoadJavaVM(jvmpath, &ifn)) { exit(6); },通过java_md.c的LoadJavaVM函数来加载整个JVM虚拟机,该方法有2个参数: 第一个是我们之前获取得到的jvm.dll的绝对路径;/* Load the Java VM DLL */ if ((handle = LoadLibrary(jvmpath)) == 0) { ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE); return JNI_FALSE; } /* Now get the function addresses */ ifn->CreateJavaVM = (void *)GetProcAddress(handle, "JNI_CreateJavaVM"); ifn->GetDefaultJavaVMInitArgs = (void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");struct JavaMainArgs { int argc; char ** argv; char * jarfile; char * classname; InvocationFunctions ifn;};ContinueInNewThread(JavaMain, threadStackSize, (void*)&args, ret);新起一个线程去执行JavaMain函数。
r = ifn->CreateJavaVM(pvm, (void **)penv, &args);。
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args)该方法有3个参数,都是从java.c的InitializeJVM函数传过来的: 第一个参数是javaVM指针的指针;
result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again); if (result == JNI_OK) { JavaThread *thread = JavaThrad::current(); /* thread is thread_in_vm heere */ *vm = (JavaVM *)(&main_vm); *(JNIEnv**)penv = thread->jni_environment();if (jarfile != 0) { mainClassName = GetMainClassName(env, jarfile); ..... } else { mainClassName = NewPlatformString(env, classname); .... }如果执行的是jar文件,则会通过GetMainClassName函数查找jar中的MainClass.具体逻辑就是先实例化java/util/jar/JarFile类,然后获取执行的jar文件中的Manifest对象的"Main-Class"属性。——即jar包中的META-INF/MANIFEST.MF文件的"Main-Class"属性。mainArgs = NewPlatformStringArray(env, argv, argc);,然后调用前面获取到的JNIEnv实例调用CallStaticVoidMethod方法执行入口函数。
/* Invoke main method. */ (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);。