jvm运行流程

Java虚拟机(JVM)是运行Java字节码的虚拟机。JVM的运行流程可以分为几个阶段:加载(Loading)、链接(Linking)、初始化(Initialization)、使用(Using)和卸载(Unloading)。JVM运行时,主要通过类加载器(ClassLoader)、执行引擎(Execution Engine)以及内存区域(Memory Areas)协同工作来完成任务。

类加载(Class Loading)

JVM 启动时,主类(带有 main 方法的类)会被加载。JVM 使用了不同级别的类加载器:

  1. 引导类加载器(Bootstrap Class Loader):用原生代码实现,加载 JVM 基础核心类库。
  2. 扩展类加载器(Extension Class Loader) :加载扩展库(jre/lib/ext 或者 Java 系统变量 java.ext.dirs 指定的目录中的 JAR 包)。
  3. 系统类加载器(System/Application Class Loader) :加载系统类路径(classpath)上的类库。

在 OpenJDK 源码中,这部分对应的是 ClassLoader 类和 sun.misc.Launcher 类。

java 复制代码
// 伪代码 - JVM 类加载
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class<?> mainClass = cl.loadClass("MainClassName");

链接(Linking)

加载后,类会经过以下链接步骤:

  1. 验证(Verification):确保加载的类符合 JVM 规范,检查格式、语法、安全性等。
  2. 准备(Preparation):为类的静态字段分配内存,并设置默认初始化值。
  3. 解析(Resolution):将常量池中的符号引用替换成直接引用。

在 HotSpot 的源码中,可以在 instanceKlass.cpp 中找到类链接的实现。

初始化(Initialization)

类初始化包括为静态变量赋值及执行静态代码块。

java 复制代码
// Java 代码 - 类初始化
public class Example {
    static {
        // 代码块,类初始化时执行
        System.out.println("Class Example is initialized.");
    }
}

在 HotSpot 实现中,查看 InstanceKlass::initialize() 方法可以看到类初始化的过程。

执行(Execution)

类被初始化后,JVM 会调用 main 方法开始执行程序。

java 复制代码
// 伪代码 - JVM 执行 main 方法
Method m = mainClass.getMethod("main", String[].class);
m.invoke(null, (Object)args);

在 HotSpot VM 源码中,解释器执行字节码的部分由 interpreter.cpp 实现,而 JIT 编译则由 c1_Compiler.cppc2_Compiler.cpp 等文件实现。

垃圾回收(Garbage Collection)

JVM 在堆内存管理对象实例。当对象不再引用时,垃圾收集器会回收内存。这个过程是自动的,但是可以通过代码触发。

java 复制代码
System.gc(); // 提示 JVM 进行垃圾回收

垃圾回收的代码分布在 HotSpot 源码中的 share/vm/gc/ 目录下。

退出(Shutdown)

程序执行完毕后或者调用 System.exit() 会触发 JVM 退出流程,JVM 会卸载载入的类,并释放所有的资源。

HotSpot VM 中处理类卸载的相关代码通常在 classLoader.cppsystemDictionary.cpp 中。

总结:

以上各阶段的细节均可在 OpenJDK 的 HotSpot 源码中找到。要理解这些源码,需要具备 C++ 语言的知识,同时对 JVM 的内部结构和工作原理有较深理解。每个 JVM 实现的具体细节可能有所不同,但它们都遵循 JVM 规范。

为了更深入地理解 JVM 的工作原理,建议查阅《深入理解 Java 虚拟机》等专业书籍,并在具备一定基础后,直接阅读 OpenJDK 的源码。同时,可以通过调试工具(如 VisualVM 或 JConsole)来实时监控 JVM 的性能指标和行为。这样做可以帮助你更好地理解 JVM 的运行机制。

相关推荐
有梦想的攻城狮16 分钟前
Django使用介绍
后端·python·django
IT_陈寒36 分钟前
2025年React生态最新趋势:我从Redux迁移到Zustand后性能提升40%的心得
前端·人工智能·后端
superman超哥40 分钟前
Rust VecDeque 的环形缓冲区设计:高效双端队列的奥秘
开发语言·后端·rust·rust vecdeque·环形缓冲区设计·高效双端队列
半路程序员42 分钟前
Go内存泄漏排查pprof和trace使用
开发语言·后端·golang
WongLeer44 分钟前
Go + GORM 多级分类实现方案对比:内存建树、循环查询与 Preload
开发语言·后端·mysql·golang·gorm
Victor3561 小时前
Hibernate(34)Hibernate的别名(Alias)是什么?
后端
superman超哥1 小时前
Rust HashMap的哈希算法与冲突解决:高性能关联容器的内部机制
开发语言·后端·rust·哈希算法·编程语言·冲突解决·rust hashmap
Victor3561 小时前
Hibernate(33) Hibernate的投影(Projections)是什么?
后端
a程序小傲1 小时前
【Node】单线程的Node.js为什么可以实现多线程?
java·数据库·后端·面试·node.js
奋进的芋圆10 小时前
DataSyncManager 详解与 Spring Boot 迁移指南
java·spring boot·后端