收集工作是单线程的,并且在进行垃圾收集过程中,会进入Stop-The-World 状态。
Serial Old,作用于老年代,采用标记-整理(Mark=Compact)算法,区别于新生代的复制算法。
Serial GC 的对应 JVM 参数是:
-XX: UseSerialGC
ParNewGC新生代GC 实现,实际上是 Serial GC 的多线程版本。最常见的应用场景是配合老年代的CMS GC 工作,下面是对应参数:
-XX: UseConcMarkSweepGC -XX: UseParNewGC
CMS(Concurrent Mark Sweep)GC基于标记-清理(Mark-Sweep)算法,设计目标是尽量减少停顿时间,这一点对于Web等反应时间敏感的应用非常重要。
存在着内存碎片化问题,所以难以避免在长时间运行等情况下发生full GC,导致恶劣的停顿。
Parallel GC吞吐量优先的GC,其特点是新生代和老年代都是并行进行的。
-XX: UseParallelGC
G1 GC兼顾吞吐量和停顿时间的GC 实现,是Oracle JDK 9 以后的默认GC 选项。
G1 GC 仍然存在着年代的概念,但是其内存结构并不是简单的条带式划分,而是类似棋盘的一个个region。Region 直接是复制算法,但整体上可看作是标记-整理(Mark-Compact)算法,可以有效避免内存碎片,尤其是当Java 堆 非常大的时候,G1 的优势更加明显。
第一,Java 应用不断创建对象,通常都是分配在Eden 区域,当其空间占用达到一定阈值时,触发minor GC。仍然被引用的对象(绿色方块)存活下来,被复制到JVM 选择的Survivor 区域,而没有被引用的对象(黄色方块)则被回收。
注意:存活对象标记了“数字1”,这是为了表明对象的存活时间。
第二,经过一次Minor GC,Eden 就会空闲下来,直到再次达到Minor GC 触发条件,这个时候,另外一个Survivor 区域则会成为 to 区域,Eden 区域的存活对象和 From 区域对象,都会被复制到 to 区域,并且存活的年龄计算会加 1。
第三,类似第二步的过程,会发生很多次,直到有对象年龄计算达到阈值,这个时候就会发生所谓的晋升(Promotion)过程,如下图所示,超过阈值的对象会被晋升到老年代。
这个阈值可以通过参数指定:
-XX:MaxTenuringThreshold 参数(默认值:15)
在JDK 11 中,又增加了两种全新的GC 方式:
即使是 Serial GC,虽然比较古老,但是简单的设计和实现未必就是过时的,它本身的开销很小,不管是GC 相关数据结构的开销,还是线程的开销,都是非常小的,所以随着云计算的兴起,在Serverless 等新的应用场景下,Serial GC 找到了新的舞台。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved