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

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

第一阶段:加载 (Loading)

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

  1. 1.

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

  2. 2.

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

  3. 3.

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

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

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

  4. 4.

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


第二阶段:链接 (Linking)

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

  1. 1.

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

  2. 2.

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

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

  3. 3.

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

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

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

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


第三阶段:初始化 (Initialization)

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

  1. 1.

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

  2. 2.

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

  3. 3.

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

  4. 4.

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


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

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

  1. 1.

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

  2. 2.

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

  3. 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. 4.

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

  5. 5.

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

  6. 6.

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921605.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921605.shtml
英文地址,请注明出处:http://en.pswp.cn/news/921605.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聚焦诊断管理(DM)的传输层设计、诊断服务器实现、事件与通信管理、生命周期与报告五大核心模块

聚焦诊断管理(DM)的传输层设计、诊断服务器实现、事件与通信管理、生命周期与报告五大核心模块,明确 UDS(ISO 14229-1)与 SOVD(ASAM 服务化诊断)的功能逻辑、交互流程及规范性要求(SWS_DM 系列)。 1 UDS 传输层(UDS Transport Layer) 作为 DM 与诊断客户端的 UDS …

关于npm的钩子函数

一、npm scripts 的生命周期钩子&#xff08;Lifecycle Scripts&#xff09; npm 提供了一些 ​​特殊的 script 名称​​&#xff0c;它们是 ​​生命周期钩子​​&#xff0c;会在特定时机 ​​自动执行​​。这些钩子包括&#xff1a; 1.prepublishOnly(在 npm publish之前执…

167.在Vue3中使用OpenLayers模仿共享单车,判断点是否放在规划的电子围栏内

一、前言大家好&#xff0c;这里分享一个 Vue3 OpenLayers 的小案例&#xff1a; 模仿共享单车的电子围栏功能&#xff0c;用户在地图上绘制停泊点时&#xff0c;系统会自动判断该点是否在规划好的电子围栏内&#xff08;多边形或圆形&#xff09;。这个功能在实际项目中有很大…

键盘上面有F3,四,R,F,V,按下没有反应,维修记录

打开游戏&#xff0c;按了好几遍F&#xff0c;结果都没反应&#xff0c;但是左右上下行走是没问题的。一脸懵逼&#xff1f;&#xff1f;&#xff1f;打开键盘测试网页&#xff0c;发现有一列没反应&#xff0c;F1不是&#xff0c;F1我定义了一个快捷键&#xff0c;跟测试冲突了…

8051单片机-成为点灯大师

第三章 成为点灯大师 1. 硬件设计 上一章说到&#xff0c;怎么点亮LED灯&#xff0c;很简单啊&#xff0c;就是把P2口设置成低电平就行了。接下来让我们更进一步&#xff0c;完成LED闪烁、流水灯实验2. 软件设计 2.1 LED闪烁实验 为了使LED闪烁&#xff0c;我们自然而然的想到要…

Rust 日志库完全指南:从入门到精通

GitHub 仓库: https://github.com/zhouByte-hub/rust-study ⭐ 如果这个项目对您有帮助&#xff0c;请给我一个 star&#xff01; 在 Rust 生态系统中&#xff0c;日志处理是一个至关重要的环节。无论是开发小型应用还是大型系统&#xff0c;良好的日志记录都能帮助我们追踪问题…

【科研绘图系列】R语言绘制论文合集图

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍 数据准备与过滤 统计分析 可视化绘图 抗药性分析 系统发育分析 加载R包 数据下载 Supp figure 1 Fig 1a Fig 1c Fig 1d Fig 1e Fig 1f Supp figure 3 Supp figure 4 Supp figure 5…

【c++】从三个类的设计看软件架构的哲学思考

从三个类的设计看软件架构的哲学思考 文章目录从三个类的设计看软件架构的哲学思考前言一、OP类&#xff1a;系统工程的安全守护者设计特点设计哲学适用场景现实类比二、VarReviser类&#xff1a;版本控制的严谨管理者设计特点设计哲学适用场景现实类比三、Model类&#xff1a;…

人工智能优化SEO关键词的实战策略

本文聚焦智能技术如何革新关键词优化实践&#xff0c;系统解析提升网站排名的核心路径。重点探讨语义分析如何精准匹配用户意图、长尾词智能挖掘怎样解锁高潜力流量&#xff0c;并详解工具筛选高转化关键词的五大实用策略。通过实战案例说明技术如何突破流量增长瓶颈&#xff0…

【c++】c++第一课:命名空间

文章目录1.C的第⼀个程序2.命名空间2.1 namespace的价值2.2 namespace的定义2.3 命名空间使⽤最新的c标准&#xff08;建议收藏&#xff09; 1.C的第⼀个程序 C兼容C语⾔绝⼤多数的语法&#xff0c;所以C语⾔实现的helloworld依旧可以运⾏&#xff0c;C中需要把定义⽂件代码后…

版本发布流程手册:Release分支规范与Bug分级标准全解析

在软件交付日益高频、用户需求快速迭代的今天&#xff0c;版本发布流程的规范性直接决定了团队的交付效率、产品质量和用户满意度。然而&#xff0c;许多团队仍面临以下痛点&#xff1a; 发布混乱&#xff1a;分支管理随意&#xff0c;代码冲突频发&#xff1b;质量失控&#…

什么是CA根证书

CA 根证书&#xff08;Certificate Authority Root Certificate&#xff09;是 数字证书体系&#xff08;PKI&#xff0c;Public Key Infrastructure&#xff09; 中的核心证书。它有几个关键点&#xff1a;1. 定义 CA&#xff08;Certificate Authority&#xff09;&#xff1…

git push -u origin main 这个-u起什么作用

git push -u origin main 里的 -u 等价于 --set-upstream&#xff0c;它的作用是&#xff1a;&#x1f449; 把本地分支 main 和远程分支 origin/main 绑定&#xff08;建立追踪关系&#xff09;。&#x1f539; 具体效果第一次推送分支时&#xff0c;如果加了 -u&#xff1a;本…

【Unity基础】两个关于UGUI中Text对非英文字体支持的问题

问题1&#xff1a;Unity中为什么UGUI中的Text(Textmeshpro&#xff09;默认不支持非英文字体&#xff0c;而legacy中的text却可以呢&#xff1f; 在Unity中&#xff0c;TextMeshPro&#xff08;TMP&#xff09;默认不支持非英文字体&#xff0c;而Legacy Text支持&#xff0c;主…

碎片时间干活的好手(requestIdleCallback)

&#x1f7e2; What —— 它是什么&#xff1f; requestIdleCallback(callback[, options]) 是浏览器提供的一个 API&#xff0c;用来在主线程空闲时执行一些优先级不高的任务。 它的特点&#xff1a; 异步执行&#xff1a;不会打断关键的渲染、交互、动画。节省性能&#xff1…

第三方网站测评:【WEB应用文件包含漏洞(LFI/RFI)的测试步骤】

文件包含漏洞分为本地文件包含(LFI)和远程文件包含(RFI)两类。LFI允许读取服务器本地文件,RFI可执行远程服务器上的恶意代码。PHP应用中include()、require()等函数未正确过滤用户输入时易产生此类漏洞。 检测URL中可能包含文件的参数,常见特征如下: 参数名包含file、pa…

网络爬虫(web crawler)

文章目录一、什么是网络爬虫二、爬虫工作流程详解第1步&#xff1a;起始点 - URL种子库&#xff08;Seed URLs&#xff09;第2步&#xff1a;大脑 - 调度器&#xff08;Scheduler&#xff09;第3步&#xff1a;双手 - 网页下载器&#xff08;Downloader&#xff09;第4步&#…

redis的高可用(哨兵)

Redis 的主从复制模式下&#xff0c;一旦主节点由于故障不能提供服务&#xff0c;需要人工进行主从切换&#xff0c;同时大量的客户端需要被通知切换到新的主节点上&#xff0c;对于上了一定规模的应用来说&#xff0c;这种方案是无法接受的&#xff0c;于是Redis从2.8开始提供…

安徽某能源企业积极推进运维智能化转型,引入高压配电房机器人巡检系统

在工业自动化与智能化深度融合的当下&#xff0c;机器人技术已成为能源行业提质增效的关键支撑。特别是在配电房这类高压电力核心区域的运维工作中&#xff0c;传统人工巡检不仅面临效率低下、巡检周期长的困境&#xff0c;更因人员直接接触高压设备而存在极高的安全风险。此&a…

数据结构_二叉平衡树

#include <stdio.h> #include <stdlib.h> #define max(a,b) ((a > b)? (a):(b))//平衡二叉树的节点结构 typedef struct AVL_TreeNode{int data; //数据域struct AVL_TreeNode* l;struct AVL_TreeNode* r;int h;//记录树的高度&#xff0c;用于计算平衡因子 }…