JVM | JVM 的启动及 java -version 的执行过程

本贴最后更新于 1761 天前,其中的信息可能已经时移俗易

开头说两句

Java 基础 Demo 站: https://www.javastudy.cloud
Java 中高级开发博客: https://www.lixiang.red
Java 学习公众号: java 技术大本营
java_subscribe

tomcat 有没有 main 函数

在学启动的时候, 我一直在想一个以前的 java 问题,就是 Tomcat 有没有 Main 函数, 答案肯定是有! 那么 jvm 做为一个 C++ 应用程序, 他也肯定有 man 函数, 我们坚定这一点, 然后再去看代码

JVM 的 main 函数

我们可以通过全局搜索可以定位到 main 函数的位置,如下图所示:

h7P1fw

点进去文件可以看到 jvm 对不同的处理器 32 位/64 位和不同的启动类型 javaw/java 做不了同的处理.

JAVAW 的启动头是

int WINAPI
WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
{
    int margc;
    char** margv;
    int jargc;
    char** jargv;
    const jboolean const_javaw = JNI_TRUE;

    __initenv = _environ;

java 的启动头是

JNIEXPORT int
main(int argc, char **argv)
{
    int margc;
    char** margv;
    int jargc;
    char** jargv;
    const jboolean const_javaw = JNI_FALSE;

往下的方法体中可以看到大都是对参数进行的处理, 直到这个文件的最后,开始 Launch 启动

return JLI_Launch(margc, margv,
               jargc, (const char**) jargv,
               0, NULL,
               VERSION_STRING,
               DOT_VERSION,
               (const_progname != NULL) ? const_progname : *margv,
               (const_launcher != NULL) ? const_launcher : *margv,
               jargc > 0,
               const_cpwildcard, const_javaw, 0)

该方法的实现是在 src/java.base/share/native/libjli/java.c 这个目录下

在这个方法中, 我们可以看到, 主要是以下几步:

调用方法 CreateExecutionEnvironment 创建运行环境

调用方法 LoadJavaVM 去加载 libjvm

调用方法 ParseArguments 去解析参数

最后调用 JVMInit 去启动 JVM

JVMInit

这个方法就跟操作系统有关了,如下图所示不同的系统会去执行不同的文件的中代码

3eEjz4

在对应系统的 JVMInit 的方法中, 会调用 java.c 中的 ContinueInNewThread 方法,并在方法 ContinueInNewThread 中调用不同操作系统的 ContinueInNewThread0 方法,如下图所示:

4JJzgY

这样我们就来到了第一天,用 Clion 调试 JDK 源码时的 JavaMain 方法

JavaMain 方法

这里还是以打印版本号为例,可以看到在 444 行,有如下代码:

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

可知实际调用的是 PrintJavaVersion(env,showVersion) 这个方法.

其实现如下:

static void
PrintJavaVersion(JNIEnv *env, jboolean extraLF)
{
    jclass ver;
    jmethodID print;
		// 找到指定的类
    NULL_CHECK(ver = FindBootStrapClass(env, "java/lang/VersionProps"));
  	// 找到指定的方法
    NULL_CHECK(print = (*env)->GetStaticMethodID(env,
                                                 ver,
                                                 (extraLF == JNI_TRUE) ? "println" : "print",
                                                 "(Z)V"
                                                 )
              );
		// 调用这个方法
    (*env)->CallStaticVoidMethod(env, ver, print, printTo);
}

我们在 Idea 中,引入 11 的 JDK , 然后就可以看到对应的输出

pSUMDB

总结

至此,java -version 的执行过程,我们是已经了解了, 而且借着 java -version 我们还了解到了 jvm 虚拟机启动的过程. 这部分是后面的基础, 希望小伙伴们能跟着小刀一起,落实这方面的知识,加油!

  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...