深入解析JVM源码 - 创建HotSpot

Posted JavaEdge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入解析JVM源码 - 创建HotSpot相关的知识,希望对你有一定的参考价值。

1 程序主入口

src/java.base/share/native/launcher/main.c

main函数返回了JLI_Launch()函数,位于 src/java.base/share/native/libjli/java.c

2 java.c # JLI_Launch()

JavaMain()是Java主程序的native调用。

在该方法里会执行虚拟机的初始化,获取Java程序主类及main方法,然后通过JNI调用main方法, 自此,整个JVM进程执行结束,最终退出。

int JavaMain(void *_args) {
JavaMainArgs *args = (JavaMainArgs *) _args;
int argc = args->argc;
char **argv = args->argv;
int mode = args->mode;
char *what = args->what;
InvocationFunctions ifn = args->ifn;

JavaVM *vm = 0;
JNIEnv *env = 0;
jclass mainClass = NULL;
jclass appClass = NULL; // 实际启动的应用程序类
jmethodID mainID;
jobjectArray mainArgs;
int ret = 0;
jlong start, end;

RegisterThread();

/* 初始化虚拟机 */
start = CounterGet();
if (!InitializeJVM(&vm, &env, &ifn)) {
JLI_ReportErrorMessage(JVM_ERROR1);
exit(1);
}

if (showSettings != NULL) {
ShowSettings(env, showSettings);
CHECK_EXCEPTION_LEAVE(1);
}

// 显示已解决的模块并继续
if (showResolvedModules) {
ShowResolvedModules(env);
CHECK_EXCEPTION_LEAVE(1);
}

// 列出可观察的模块,然后退出
if (listModules) {
ListModules(env);
CHECK_EXCEPTION_LEAVE(1);
LEAVE();
}

// 描述一个模块,然后退出
if (describeModule != NULL) {
DescribeModule(env, describeModule);
CHECK_EXCEPTION_LEAVE(1);
LEAVE();
}

if (printVersion || showVersion) {
PrintJavaVersion(env, showVersion);
CHECK_EXCEPTION_LEAVE(0);
if (printVersion) {
LEAVE();
}
}

// 模块在启动时已通过验证,因此退出
if (validateModules) {
LEAVE();
}

/* 如果用户未指定类名或JAR文件 */
if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) {
PrintUsage(env, printXUsage);
CHECK_EXCEPTION_LEAVE(1);
LEAVE();
}

FreeKnownVMs(); /* 最后一次可能的PrintUsage之后 */

if (JLI_IsTraceLauncher()) {
end = CounterGet();
JLI_TraceLauncher("%ld micro seconds to InitializeJVM\n",
(long) (jint) Counter2Micros(end - start));
}

/* 在此阶段,argc / argv具有应用程序的参数 */
if (JLI_IsTraceLauncher()) {
int i;
printf("%s is '%s'\n", launchModeNames[mode], what);
printf("App's argc is %d\n", argc);
for (i = 0; i < argc; i++) {
printf(" argv[%2d] = '%s'\n", i, argv[i]);
}
}

ret = 1;

/*
* 加载Java程序的main方法,如果没找到则退出
*
* 获取应用程序的主类. 它还检查main方法是否存在
* 请参见 bugid 5030265。已经从 manifest 中解析了 Main-Class 名称,但是没有为UTF-8支持对其进行正确解析。
* 因此,此处的代码将忽略先前提取的值,并使用预先存在的代码重新提取该值。
* 这可能是发布周期权宜之计。
* 但是,还发现在环境中传递某些字符集在Windows的某些变体中具有“奇怪”的行为。
* 因此,也许永远都不应增强启动器本地的清单解析代码。
* Hence the code here ignores the value previously extracted and
* uses the pre-existing code to reextract the value. This is
* possibly an end of release cycle expedient.
* Hence, maybe the manifest parsing code local to the
* launcher should never be enhanced.
*
* 因此,未来的工作应:
* 1) 更正本地解析代码,并验证Main-Class属性是否已正确通过所有环境,
* 2) 删除通过环境维护 main_class 的方法(并删除这些注释).
*
* 此方法还可以正确处理启动可能具有或不具有Main-Class清单条目的现有JavaFX应用程序.
*/

mainClass = LoadMainClass(env, mode, what);
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
/*
* 获取程序主类Class对象
*
* 在某些情况下,当启动 需要帮助程序的 应用程序(例如,没有main方法的JavaFX应用程序)时,
* mainClass将不是应用程序自己的主类,而是帮助程序类。
* 为了使UI中的内容保持一致,我们需要跟踪和报告应用程序主类。
*/

appClass = GetApplicationClass(env);
NULL_CHECK_RETURN_VALUE(appClass, -1);

/* 构建平台特定的参数数组(构建main方法的参数列表) */
mainArgs = CreateApplicationArgs(env, argv, argc);
CHECK_EXCEPTION_NULL_LEAVE(mainArgs);

if (dryRun) {
ret = 0;
LEAVE();
}

/*
* PostJVMInit 使用类名称作为用于GUI的应用程序名称
* 例如, 在 OSX 上, 这会在菜单栏中为SWT和JavaFX设置应用程序名称.
* 因此, 我们将在此处传递实际的应用程序类而不是mainClass, 因为这可能是启动器或帮助程序类, 而不是应用程序类.
*/

PostJVMInit(env, appClass, vm);
CHECK_EXCEPTION_LEAVE(1);

/*
* 获取main方法ID
*
* LoadMainClass不仅加载主类,还将确保主方法的签名正确,这样就不需要再进一步检查了.
* 这里调用main方法,以便无关的Java堆栈不在应用程序stack trace中.
*/

mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);

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

/*
* 如果main抛出异常,则启动程序的退出码(在没有对System.exit的调用的情况下)将为非零。
*/

ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;

LEAVE();
}

该方法中调用的InitializeJVM()方法会执行一系列关于虚拟机的分配、挂载、初始化等工作, 且听下回分解


以上是关于深入解析JVM源码 - 创建HotSpot的主要内容,如果未能解决你的问题,请参考以下文章

1.3 万字 13 图!JVM 史上最最最完整深入解析

深入理解JVM——揭开HotSpot对象创建的奥秘

JVM学习-HotSpot虚拟机对象探秘

JVM 史上最最最完整深入解析(12000 字噢)

jvm,深入理解java虚拟机,HotSpot虚拟机对象探秘

jvm,深入理解java虚拟机,HotSpot虚拟机对象探秘