一、JVM垃圾回收(GC, Garbage Collection)的概念
JVM垃圾回收 是指自动管理内存,对程序中不再使用的对象进行回收,以释放内存空间并防止内存泄漏。Java采用自动垃圾回收机制(Automatic Garbage Collection),由 垃圾回收器(Garbage Collector, GC) 自动完成,无需程序员手动释放内存。
二、JVM内存结构
在进行垃圾回收之前,理解 JVM内存结构 很关键。JVM内存主要分为以下几部分:
-
程序计数器(Program Counter Register)
- 线程私有,用于存储当前线程执行的字节码指令地址。
-
Java虚拟机栈(Java Virtual Machine Stack)
- 线程私有,存储方法执行的局部变量表、操作数栈等。
-
本地方法栈(Native Method Stack)
- 线程私有,执行本地方法(如C、C++)。
-
堆(Heap, 重点GC区域)
- 线程共享,用于存放对象实例,进行垃圾回收的主要区域。
- 又分为 新生代 (Young Generation) 和 老年代 (Old Generation)。
-
方法区(Method Area, 又称元空间 Metaspace)
- 线程共享,存储类信息、常量、静态变量、即时编译器(JIT)代码等。
三、堆内存分代模型
1. 新生代 (Young Generation)
- Eden区: 新生对象首先分配到Eden区。
- Survivor区: 包括 S0 (Survivor 0) 和 S1 (Survivor 1) 两个区,用于在Minor GC后存活对象的交换存储。
- 特点: 新生代回收频繁,存活率低,使用 复制算法 (Copying Algorithm)。
2. 老年代 (Old Generation)
- 存放经历多次Minor GC仍存活的对象,通常生命周期较长。
- 特点: 回收频率低,存活率高,使用 标记-清除算法 (Mark-Sweep) 或标记-整理算法 (Mark-Compact)。
3. 方法区 (Metaspace)
- 存储类信息、常量池、方法代码等。使用本地内存,不在堆中。
四、垃圾回收算法
1. 标记-清除算法 (Mark-Sweep)
- 过程:
- 标记: 标记所有存活的对象。
- 清除: 回收未标记的对象。
- 优点: 简单直接。
- 缺点: 容易产生 内存碎片,降低分配效率。
2. 复制算法 (Copying Algorithm)
- 过程:
- 将新生代分为 Eden区 和两个Survivor区 (S0, S1)。
- 活动对象从Eden复制到空的Survivor区,回收Eden区。
- 每次只使用Eden和一个Survivor区,交换使用两个Survivor区。
- 优点: 没有碎片,分配连续内存快。
- 缺点: 空间浪费 (通常Eden:Survivor = 8:1:1)。
3. 标记-整理算法 (Mark-Compact)
- 过程:
- 标记存活对象。
- 整理: 将存活对象向内存一端移动,清理末端内存。
- 优点: 解决标记-清除的碎片问题,适合老年代。
- 缺点: 移动对象成本较高。
4. 分代收集算法 (Generational GC)
- 综合使用上述算法,根据 对象存活周期 进行分代:
- 新生代 (Young Generation): 使用 复制算法,回收频繁,生命周期短。
- 老年代 (Old Generation): 使用 标记-清除 或 标记-整理算法,回收频率低。
- 优点: 针对不同对象特点优化,提高回收效率。
五、垃圾回收器(Garbage Collector, GC)种类
1. Serial GC(串行收集器)
- 特点: 单线程,STW (Stop-The-World) 时间长,适合小内存。
- 使用:
-XX:+UseSerialGC
。
2. ParNew GC
- 特点: Serial GC 的多线程版本,常用于新生代,配合 CMS GC 使用。
- 使用:
-XX:+UseParNewGC
。
3. Parallel GC(并行收集器)
- 特点: 关注吞吐量,采用多线程并行处理。
- 使用:
-XX:+UseParallelGC
。
4. CMS GC(Concurrent Mark-Sweep GC)
- 特点: 低延迟,针对老年代的垃圾回收,分为 标记和清除 阶段。
- 缺点: 容易产生碎片,内存利用率不高。
- 使用:
-XX:+UseConcMarkSweepGC
。
5. G1 GC(Garbage First GC)
- 特点: 面向服务端,支持大内存,分区管理内存,避免碎片。
- 分区策略: 将堆划分为多个Region,按优先级回收。
- 使用:
-XX:+UseG1GC
。
六、垃圾回收触发条件
- 新生代满时,触发 Minor GC。
- 老年代满时,触发 Major GC / Full GC。
- 方法区或永久代满时,触发 Full GC。
七、Full GC 和 Minor GC 的区别
对比维度 | Minor GC | Full GC |
---|---|---|
触发条件 | 新生代满时触发 | 老年代或方法区满时触发 |
影响范围 | 仅新生代 (Eden + Survivor) | 整个堆 (新生代 + 老年代 + 方法区) |
停顿时间 (STW) | 短 | 长 |
频率 | 高 | 低 |
八、JVM调优常用参数
-
设置新生代和老年代比例
-XX:NewRatio=2
(新生代:老年代 = 1:2)
-
设置Eden和Survivor比例
-XX:SurvivorRatio=8
(Eden:Survivor = 8:1:1)
-
设置最大和最小堆内存
-Xms512m
(最小)-Xmx1024m
(最大)
-
选择垃圾回收器
-XX:+UseG1GC
(G1收集器)-XX:+UseConcMarkSweepGC
(CMS收集器)
九、总结
- 分代回收策略 通过新生代和老年代的区分提高效率。
- 不同算法组合使用 满足不同对象存活周期的要求。
- 选择合适的GC策略 根据应用场景权衡 吞吐量 和 延迟。
JVM垃圾回收机制的核心在于 分代管理、合理选择算法和回收器、配置调优,以便在性能和内存使用之间取得平衡。 😊