一个Java的main方法在JVM中的执行流程示例详解

 更新时间:2025年09月17日 08:58:38   作者:斯kk  
main方法是Java程序的入口点,程序从这里开始执行,这篇文章主要介绍了一个Java的main方法在JVM中执行流程的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一个Java的main方法在JVM中的执行流程可以分为​​四大阶段​​:​​加载 -> 链接 -> 初始化 -> 执行​​。

// HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        String message = "Hello, JVM!";
        System.out.println(message);
    }
}

第一阶段:加载 (Loading)

​目标:找到并加载类的二进制数据。​

1.​​编译​​:你执行 javac HelloWorld.java。Java编译器将源代码编译成JVM能理解的字节码,存储在 HelloWorld.class文件中。这个文件包含了一个​​类常量池(Constant Pool)​​,里面有各种符号引用,比如 Hello, JVM!这个字符串的字面量、System/out/println等类名、方法名和字段名。

2.​​启动JVM​​:你执行 java HelloWorld。操作系统会启动JVM进程。

3.​​寻找类​​:JVM通过​​类加载器(ClassLoader)​​ 来加载 HelloWorld类。

 Bootstrap ClassLoader​​:首先,启动类加载器会去加载JAVA_HOME/lib下的核心类库,如 java.lang包(包括ObjectStringSystem等)。

• Application ClassLoader​​:然后,应用程序类加载器开始工作,它在你的CLASSPATH(默认是当前目录)下寻找 HelloWorld.class文件。

4.​​创建Class对象​​:JVM成功读取 HelloWorld.class的二进制字节流后,会将其转换为​​方法区(Metaspace)​​ 中的运行时数据结构,并同时在 ​​Java堆(Heap)​​ 中创建一个 java.lang.Class对象,作为方法区这些数据的访问入口。这个 Class对象封装了类的所有元信息(如方法、字段等)。

第二阶段:链接 (Linking)

​目标:将加载到方法区的二进制数据合并到JVM运行时状态中。​​ 此阶段细分为三步:

1.​​验证 (Verification)​​:JVM会严格检查 HelloWorld.class文件的格式、元数据、字节码等是否符合规范且不会危害JVM自身安全。这是一个非常重要的安全屏障。

2.​​准备 (Preparation)​​:JVM为​​类的静态变量(static variables)​​ 在方法区分配内存并设置​​初始值​​(零值)。注意,这里是初始值,不是代码中赋的值。

•例如,如果类里有 static int value = 123;,在准备阶段,value会被赋值为 0。真正的赋值 123要等到后面的初始化阶段。

3.解析 (Resolution)​​:JVM将​​类常量池​​中的​​符号引用(Symbolic References)​​ 替换为​​直接引用(Direct References)​​。

符号引用​​:就是一种约定好的形式来表示引用的目标,比如 java/lang/System.out

直接引用​​:就是一个直接指向目标的指针、偏移量或句柄。

•例如,在这一步,System.out这个符号引用会被解析为 java.io.PrintStream对象在堆内存中的实际地址。

第三阶段:初始化 (Initialization)

​目标:执行类的构造器 <clinit>()方法,为静态变量赋予程序设定的初始值。​

1.到了这一步,JVM才开始真正执行你写在Java代码中的静态语句和静态变量赋值。

2.JVM会收集类中的所有​​静态变量的赋值动作​​和​​静态代码块(static {})​​,合并生成一个唯一的 <clinit>()方法。

3.JVM会确保 <clinit>()方法在多线程环境下被正确地加锁同步执行,所以类初始化是线程安全的。

4.在我们的 HelloWorld例子中,没有静态变量和静态代码块,所以 <clinit>()方法是空的,但这一步依然会发生。

第四阶段:执行 (Execution & Runtime)

​目标:创建线程,执行字节码。​

1 . 主线程​​:JVM会为 main方法创建一个​​主线程​​。该线程拥有自己的​​程序计数器(PC)​​ 和 ​​Java虚拟机栈(JVM Stack)​​。

2 .​​ 栈帧​​:线程的每个方法调用都会在虚拟机栈中创建一个​​栈帧(Stack Frame)​​,用于存储​​局部变量表​​、​​操作数栈​​、​​动态链接​​、​​方法返回地址​​等信息。main方法是程序入口,所以第一个被压入栈的栈帧就是 main方法的栈帧。

3 .​ ​执行引擎​​:JVM的​​执行引擎​​开始解释执行 main方法栈帧中的字节码。

String message = "Hello, JVM!";

执行引擎遇到字面量 "Hello, JVM!"时,会去​​字符串常量池(String Table,位于堆中)​​ 中寻找。如果找不到,就在堆中创建一个String对象并将其引用驻留在常量池中,然后将该引用存入 main栈帧的局部变量表 message中。

System.out.println(message);

执行引擎通过之前在​​解析阶段​​已经转换好的​​直接引用​​,快速地找到 System.out对应的 PrintStream对象。

然后调用该对象的 println方法,将局部变量 message的引用(指向堆中的String对象)作为参数传入。

4 .​​ 本地方法调用​​:println方法底层是一个​​本地方法(Native Method)​​,调用的是操作系统本身的IO能力,将字符串输出到控制台。

5 .​​ 方法返回​​:main方法执行完毕,其栈帧从虚拟机栈中弹出。主线程结束。

6 .​​ JVM退出​​:所有​​非守护线程​​都结束后,JVM进程终止。

总结

到此这篇关于一个Java的main方法在JVM中执行流程的文章就介绍到这了,更多相关JVM中main方法执行流程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot与Spring MVC Spring对比及核心概念

    Spring Boot与Spring MVC Spring对比及核心概念

    这篇文章主要为大家介绍了Spring Boot与Spring MVC Spring的对比以及你需要了解的核心概念,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-03-03
  • 线程池中execute与submit的区别说明

    线程池中execute与submit的区别说明

    这篇文章主要介绍了线程池execute与submit的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SpringBoot项目嵌入RocketMQ的实现示例

    SpringBoot项目嵌入RocketMQ的实现示例

    本文主要介绍了SpringBoot项目嵌入RocketMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • Java设计模式之单例模式示例详解

    Java设计模式之单例模式示例详解

    单例模式是最简单也是最基础的设计模式之一,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。本文将通过一些示例代码为大家详细介绍一下单例模式,感兴趣的可以了解一下
    2021-12-12
  • Java System.currentTimeMillis()时间的单位转换与计算方式案例详解

    Java System.currentTimeMillis()时间的单位转换与计算方式案例详解

    这篇文章主要介绍了Java System.currentTimeMillis()时间的单位转换与计算方式案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • JAVA 中的大数字操作类详解

    JAVA 中的大数字操作类详解

    Java的BigInteger类用于处理超出int和long范围的大整数,而BigDecimal类则用于高精度的浮点数运算,这两个类都是Number的子类,提供了一系列方法执行加减乘除等运算,BigInteger不支持表示小数,只能表示整数,BigDecimal可以控制小数位数和舍入方式,感兴趣的朋友一起看看吧
    2024-10-10
  • 为什么Java是程序员受欢迎的语言这几个原因你该清楚

    为什么Java是程序员受欢迎的语言这几个原因你该清楚

    Java一直稳居程序员很受欢迎的编程语言的榜首,是企业中使用最广泛的编程语言。这篇文章主要介绍了为什么Java是程序员受欢迎的语言这几个原因你该清楚,需要的朋友可以参考下
    2020-07-07
  • 基于Java汇总Spock框架Mock静态资源经验

    基于Java汇总Spock框架Mock静态资源经验

    这篇文章主要介绍了基于Java汇总Spock框架Mock静态资源经验,前面讲了 Spock框架Mock对象、方法经验总结,今天分享一下Spock框架中Mock静态资源的实践经验汇总。分成静态资源和混合场景,需要的朋友可以参考一下
    2022-02-02
  • SpringBoot监听器的实现示例

    SpringBoot监听器的实现示例

    在SpringBoot中,你可以使用监听器来响应特定的事件,本文主要介绍了SpringBoot监听器的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • Java构建工具Gradle的安装和使用图文教程

    Java构建工具Gradle的安装和使用图文教程

    Gradle 是一个功能强大的构建工具,支持自动化和定制化的构建过程,下面这篇文章主要介绍了Java构建工具Gradle的安装和使用的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-09-09

最新评论