Java虚拟机(JVM)是运行Java字节码的虚拟机。JVM的运行流程可以分为几个阶段:加载(Loading)、链接(Linking)、初始化(Initialization)、使用(Using)和卸载(Unloading)。JVM运行时,主要通过类加载器(ClassLoader)、执行引擎(Execution Engine)以及内存区域(Memory Areas)协同工作来完成任务。
类加载(Class Loading)
JVM 启动时,主类(带有 main
方法的类)会被加载。JVM 使用了不同级别的类加载器:
- 引导类加载器(Bootstrap Class Loader):用原生代码实现,加载 JVM 基础核心类库。
- 扩展类加载器(Extension Class Loader) :加载扩展库(
jre/lib/ext
或者 Java 系统变量java.ext.dirs
指定的目录中的 JAR 包)。 - 系统类加载器(System/Application Class Loader) :加载系统类路径(
classpath
)上的类库。
在 OpenJDK 源码中,这部分对应的是 ClassLoader
类和 sun.misc.Launcher
类。
java
// 伪代码 - JVM 类加载
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class<?> mainClass = cl.loadClass("MainClassName");
链接(Linking)
加载后,类会经过以下链接步骤:
- 验证(Verification):确保加载的类符合 JVM 规范,检查格式、语法、安全性等。
- 准备(Preparation):为类的静态字段分配内存,并设置默认初始化值。
- 解析(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.cpp
和 c2_Compiler.cpp
等文件实现。
垃圾回收(Garbage Collection)
JVM 在堆内存管理对象实例。当对象不再引用时,垃圾收集器会回收内存。这个过程是自动的,但是可以通过代码触发。
java
System.gc(); // 提示 JVM 进行垃圾回收
垃圾回收的代码分布在 HotSpot 源码中的 share/vm/gc/
目录下。
退出(Shutdown)
程序执行完毕后或者调用 System.exit()
会触发 JVM 退出流程,JVM 会卸载载入的类,并释放所有的资源。
HotSpot VM 中处理类卸载的相关代码通常在 classLoader.cpp
和 systemDictionary.cpp
中。
总结:
以上各阶段的细节均可在 OpenJDK 的 HotSpot 源码中找到。要理解这些源码,需要具备 C++ 语言的知识,同时对 JVM 的内部结构和工作原理有较深理解。每个 JVM 实现的具体细节可能有所不同,但它们都遵循 JVM 规范。
为了更深入地理解 JVM 的工作原理,建议查阅《深入理解 Java 虚拟机》等专业书籍,并在具备一定基础后,直接阅读 OpenJDK 的源码。同时,可以通过调试工具(如 VisualVM 或 JConsole)来实时监控 JVM 的性能指标和行为。这样做可以帮助你更好地理解 JVM 的运行机制。