Java 虚拟机(JVM)简介
Java 虚拟机(JVM, Java Virtual Machine)是 Java 程序执行的运行时环境,负责将编译后的字节码解释为机器指令,并进行内存管理和垃圾回收。
1. JVM 结构
JVM 的主要组成部分包括以下几个部分:
- 类加载器(Class Loader Subsystem):负责将 .class 文件加载到内存中。
- 运行时数据区(Runtime Data Area):JVM 内存模型,包括方法区、堆、栈等。
- 执行引擎(Execution Engine):将字节码解释执行或编译成本地机器码。
- 本地方法接口(Native Interface):调用本地(如 C/C++)代码。
- 垃圾收集器(Garbage Collector):自动管理内存,回收不再使用的对象。
2. JVM 内存模型
JVM 内存模型分为多个区域,每个区域有不同的作用:
2.1 堆(Heap)
- 堆是用于存储所有对象实例和数组的内存区域,几乎所有的对象都在这里分配内存。
- 堆在 JVM 启动时创建,堆的大小可以通过
-Xms(初始大小)和-Xmx(最大大小)参数进行控制。

2.2 栈(Stack)
- 每个线程在执行方法时都会创建一个栈帧,存储局部变量、操作数栈、动态链接、方法出口等。
- 每个方法调用都会在栈中分配一个栈帧,方法调用结束后栈帧会被销毁。

2.3 方法区(Method Area)
- 存储类结构信息(包括类的元数据、常量、静态变量等)。
- 从 JDK 8 开始,方法区的实现变为元空间(Metaspace)。

2.4 程序计数器(Program Counter, PC Register)
- 每个线程都有一个程序计数器,记录当前线程所执行的字节码指令的地址。
- 如果是本地方法,程序计数器为空。
3. JVM 垃圾回收(Garbage Collection)
JVM 提供了自动垃圾回收机制,用于释放不再使用的对象。常见的垃圾收集器包括:
3.1 Parallel Scavenge GC
- 也是针对新生代的并行多线程收集器,使用复制算法。它关注的是吞吐量(即用户线程运行时间与总时间的比例),并允许用户设置最大垃圾收集停顿时间等参数。
3.2 CMS GC
- 虽然主要关注于低停顿时间,但它也适用于老年代。CMS GC使用标记-清除算法,并与用户线程并发执行垃圾回收。然而,它会产生内存碎片,并且在某些情况下可能需要使用Full GC来清理这些碎片。
3.3 G1 GC
- 是一种面向服务端的垃圾收集器,它同时适用于新生代和老年代。G1 GC使用了一种混合的收集算法,即在新生代使用复制算法,在老年代则使用标记-整理算法(但进行了优化以适应分代收集的需求)。G1 GC的目标是同时满足低停顿时间和高吞吐量。
4. 常用 JVM 参数
在启动 JVM 时可以使用一些参数来调整其行为:
-Xms<size>:设置 JVM 堆的初始大小。-Xmx<size>:设置 JVM 堆的最大大小。-XX:+UseG1GC:启用 G1 垃圾收集器。-XX:+PrintGCDetails:打印垃圾收集的详细信息。
5. JVM 执行流程
- 加载:类加载器将 .class 文件加载到内存。
- 链接:包括验证、准备和解析阶段。确保类的正确性,分配静态变量。
- 初始化:执行类的静态初始化器或静态块,将静态变量赋值。
6. JVM 调优
6.1 垃圾回收调优
- 观察 GC 日志,确保 GC 频率和暂停时间在可接受范围内。
- 对于响应时间敏感的应用,可以使用低延迟 GC(如 G1 或 ZGC)。
- 调整堆大小,根据应用的内存使用情况选择合适的初始和最大堆大小。
6.2 内存调优
- 如果频繁发生
OutOfMemoryError,可以考虑增加堆大小。 - 在使用 Metaspace 时,
-XX:MaxMetaspaceSize可以限制元空间大小。