1. 类加载器(Class Loader)
功能:负责将
.class
文件加载到内存,并转换为JVM可识别的数据结构。分类:
启动类加载器(Bootstrap Class Loader):加载
JAVA_HOME/lib
下的核心类库(如rt.jar
)。扩展类加载器(Extension Class Loader):加载
JAVA_HOME/lib/ext
下的扩展类。应用程序类加载器(Application Class Loader):加载用户类路径(ClassPath)的类。
自定义类加载器:用户可继承
ClassLoader
实现自定义加载逻辑。
双亲委派模型:优先由父类加载器尝试加载类,避免重复加载并确保安全。
2. 运行时数据区(Runtime Data Areas)
JVM内存管理的核心区域,分为线程私有和共享区域:
2.1 线程私有区域
程序计数器(Program Counter Register):
记录当前线程执行的字节码指令地址。
唯一不会发生内存溢出的区域。
虚拟机栈(Java Virtual Machine Stack):
存储方法调用的栈帧(Frame),每个栈帧包含:
局部变量表:方法参数和局部变量。
操作数栈:执行字节码指令的工作区。
动态链接:指向运行时常量池的方法引用。
返回地址:方法执行后的返回位置。
可能抛出
StackOverflowError
(栈深度过大)和OutOfMemoryError
(扩展失败)。
本地方法栈(Native Method Stack):
为Native方法(如C/C++实现)服务,结构与虚拟机栈类似。
2.2 线程共享区域
堆(Heap):
存储所有对象实例和数组。
分为新生代(Young Gen)和老年代(Old Gen):
新生代:Eden区、Survivor区(From/To),使用复制算法回收。
老年代:存放长期存活对象,使用标记-整理或标记-清除算法。
可能抛出
OutOfMemoryError
。
方法区(Method Area):
存储类元数据(如类名、字段、方法)、常量池、静态变量等。
实现变化:
JDK 8前:永久代(PermGen),受JVM内存限制。
JDK 8+:元空间(Metaspace),使用本地内存(Native Memory)。
运行时常量池(Runtime Constant Pool):
方法区的一部分,存储类文件中的常量(如字符串字面量、符号引用)。
3. 执行引擎(Execution Engine)
负责将字节码翻译为机器码并执行:
解释器(Interpreter):
逐行解释执行字节码,启动速度快但执行效率低。
即时编译器(JIT Compiler):
将热点代码(频繁执行的代码)编译为本地机器码,提升执行效率。
主流JVM(如HotSpot)采用分层编译(C1、C2编译器)。
垃圾回收器(Garbage Collector):
自动回收堆中不再使用的对象内存,常见算法:
标记-清除(Mark-Sweep):简单但产生内存碎片。
复制(Copying):用于新生代,无碎片但内存利用率低。
标记-整理(Mark-Compact):用于老年代,避免碎片。
4. 本地方法接口(JNI, Java Native Interface)
功能:允许Java代码调用本地方法(Native Method,如C/C++库)。
示例:
System.currentTimeMillis()
底层通过JNI调用操作系统API。
5. 本地方法库(Native Libraries)
组成:包含JVM所需的本地库(如
libjvm.so
、libjava.so
)。作用:支持JVM与操作系统交互(如线程调度、文件操作)。
JVM内存结构示意图
总结
核心组件:类加载器、运行时数据区、执行引擎、本地接口及库。
内存管理:堆和方法区是内存管理的重点,垃圾回收机制保障内存高效利用。
性能优化:通过JIT编译、分代回收、元空间替代永久代等手段提升效率。
线程安全:私有区域隔离线程状态,共享区域需同步机制(如锁、CAS)。
理解JVM组成及工作原理,是优化Java程序性能、解决内存泄漏和并发问题的关键基础。