1. 堆空间与对象晋升
堆空间是垃圾回收器的主要工作区域,堆空间根据分代收集理论可分为年轻代与老年代,元空间(使用本地内存,java8以前称之为永久代),年轻代分为Eden区、Survivor0区和Survicor1区,一般按8:1:1分配年轻代空间。创建对象一般创建时在Eden区,经历垃圾回收之后,对象的age增加,逐渐向老年代迁移,具体的对象晋升过程如下所示:
2. 垃圾回收算法与垃圾回收器对比
2.1 三大基本垃圾回收算法
-
标记-清除算法
原理:堆空间标记存活对象(从GC Roots可达的对象),清除非存活对象。
缺点:会产生内存碎片。
适合:老年代。
-
标记-整理算法
原理:标记存活对象后,将其向内存一端移动,清理边界外的内存。
减少产生内存碎片
适合:老年代。
-
复制算法:
原理:内存区域一分为二,将存活对象复制到另一块内存区域,直接清空原区域。
适合:无碎片,适合对象存活率低的年轻代。
2.2 垃圾回收期的对比
垃圾回收器的对比(Serial/CMS/G1) | |||
---|---|---|---|
特性 | Serial | CMS | G1 |
算法 | 老年代-标记整理 新生代-复制算法 | 针对老年代-标记清除算法 与ParNew新生代收集器共同使用 | 标记 - 压缩算法 |
线程模型 | 单线程 | 多线程(并发) | 多线程(并发+并行) |
STW时间 | 长 | 短(FullGC时间长) | 可控(可配置目标) |
内存碎片 | 无(压缩算法) | 有 | 较少(部分压缩) |
吞吐量 | 低 | 中等 | 高 |
适应堆大小 | 小堆(<100MB) | 中等堆(4-8G) | 大堆(>8G) |
延迟敏感性 | 不敏感 | 敏感 | 敏感 |
适应场景 | 嵌入式/客户端 | 低延迟的Web服务 | 大内存服务端应用 |
选择建议 | 选择建议 Serial:资源受限的小型应用。 CMS:已逐步被淘汰(Java 8 后不再推荐,Java 14 移除),仅用于旧版兼容。 G1:现代服务端应用的默认选择(Java 9+),尤其适合大内存和低延迟场景。 其他选择:对于超大堆(如 > 32GB)或超低延迟需求,可考虑 ZGC(Java 11+)或 Shenandoah(Java 12+)。 |
2.3 FullGC
FullGC会挂起客户所有线程,是需要尽量避免的垃圾回收操作,会导致FullGC的场景大致有下列几个方面:
FullGC触发场景 | |
---|---|
1. Eden区满了 | 触发Minor GC后,存活对象无法全部晋升到Survivor区将剩余的对象直接放入老年代,如果老年代空间不足以容纳这些对象,就会触发Full GC |
2.大对象分配 | 如果无法找到足够的连续空间来分配该大对象,也会触发Full GC |
3. 元空间内存不足 | 永久代(在JDK 8之前)或元空间(在JDK 8及更高版本)内存不足 |
4. System.gc() | 显式调用System.gc()方法,通知虚拟机执行Full GC |
5.Concurrent Mode Failure | CMS(Concurrent Mark-Sweep)垃圾收集器在并发标记阶段出现"Concurrent Mode Failure"时,会导致一次Full GC。 |