Java虚拟机(JVM)
JVM简介
Java虚拟机(JVM)是Java平台的核心组件,它负责执行Java字节码,提供内存管理、垃圾回收等功能。JVM使得Java程序具有"一次编写,到处运行"的特性。
JVM架构
// JVM主要组件
1. 类加载器(Class Loader)
2. 运行时数据区(Runtime Data Areas)
3. 执行引擎(Execution Engine)
4. 本地方法接口(Native Method Interface)
类加载器
类加载器负责将.class文件加载到JVM中,并生成对应的Class对象。
// 类加载过程
1. 加载(Loading)
2. 验证(Verification)
3. 准备(Preparation)
4. 解析(Resolution)
5. 初始化(Initialization)
6. 使用(Using)
7. 卸载(Unloading)
// 类加载器层次结构
- 启动类加载器(Bootstrap ClassLoader)
- 扩展类加载器(Extension ClassLoader)
- 应用类加载器(Application ClassLoader)
- 自定义类加载器(User-defined ClassLoader)
运行时数据区
JVM运行时数据区包括方法区、堆、虚拟机栈、本地方法栈和程序计数器。
// 运行时数据区结构
public class RuntimeDataAreas {
// 方法区(Method Area)
// 存储类信息、常量、静态变量等
// 堆(Heap)
// 存储对象实例和数组
// 虚拟机栈(VM Stack)
// 存储局部变量表、操作数栈等
// 本地方法栈(Native Method Stack)
// 为本地方法服务
// 程序计数器(Program Counter Register)
// 当前线程执行的字节码行号指示器
}
垃圾回收
JVM的垃圾回收机制自动管理内存,回收不再使用的对象。
// 垃圾回收算法
1. 标记-清除(Mark-Sweep)
2. 复制(Copying)
3. 标记-整理(Mark-Compact)
4. 分代收集(Generational Collection)
// 垃圾收集器
- Serial收集器
- ParNew收集器
- Parallel Scavenge收集器
- CMS收集器
- G1收集器
- ZGC收集器
JVM调优
通过调整JVM参数可以优化程序性能。
// 常用JVM参数
-Xms2048m // 初始堆大小
-Xmx2048m // 最大堆大小
-XX:NewRatio=2 // 新生代与老年代的比例
-XX:SurvivorRatio=8 // Eden区与Survivor区的比例
// 垃圾收集器选择
-XX:+UseG1GC // 使用G1收集器
-XX:+UseConcMarkSweepGC // 使用CMS收集器
// GC日志
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:gc.log
Java内存模型
Java内存模型(JMM)定义了线程与主内存之间的交互规则。
// 内存模型的关键概念
public class MemoryModel {
// 主内存(Main Memory)
// 所有线程共享的内存区域
// 工作内存(Working Memory)
// 每个线程私有的内存区域
// 内存间交互操作
// lock(锁定)
// unlock(解锁)
// read(读取)
// load(载入)
// use(使用)
// assign(赋值)
// store(存储)
// write(写入)
}
JVM工具
JDK提供了多种工具用于监控和调优JVM。
// 常用JVM工具
1. jps:显示Java进程
2. jstat:显示JVM统计信息
3. jinfo:显示JVM配置信息
4. jmap:生成堆转储快照
5. jhat:分析堆转储文件
6. jstack:显示线程快照
7. jconsole:图形化监控工具
8. VisualVM:多合一故障处理工具
实践练习
练习1:JVM参数调优
public class JVMTuningDemo {
public static void main(String[] args) {
// 创建一个内存泄漏的示例
List list = new ArrayList<>();
while (true) {
list.add(new byte[1024 * 1024]); // 每次分配1MB
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}