Java OpenResty Spring Spring Boot MySQL Redis MongoDB PostgreSQL Linux Android Nginx 面试 小程序 Arthas JVM AQS juc Kubernetes Docker DevOps


Java中的串行、并行、CMS 垃圾收集器

Java GC 大约 14495 字

GC 算法

  • 引用计数
  • 复制
  • 标记清除
  • 标记整理

垃圾收集器

  • Serial串行:为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有用户的线程,所以不适合服务器环境。
  • Parallel并行:多个垃圾收集线程并行工作,停顿的时间比串行的少,一个GC线程挂了还有另外几个GC线程,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景。
  • CMS并发标记清除:用户线程和垃圾收集线程可以同时执行(不一定是并行,可能交替执行),不需要停顿用户线程(共4步,有两步还是需要暂停一下),适用对响应时间有要求的场景。
  • G1 Grabage first:将堆内存分割成不同的区域然后并发的对其进行垃圾回收(初始标记阶段也会STW)。

-XX:+UseSerialGC -XX:+UseSerialOldGC(已被废弃) -XX:+UseParallelGC -XX:+UseConcMarkSweepGC

-XX:+UseParNewGC 新生代的垃圾回收机制 -XX:+UseParallelOldGC 老年代垃圾回收机制 -XX:+UseG1GC

DefNew:Default New Generation Tenured:Old ParNew:Parallel New Generation PSYoungGen:Parallel Scavenge ParOldGen:Parallel Old Generation

新生代: 串行GC(Serial)/(Serial Copying) 并行GC(ParNew) 并行回收GC(Parallel)/(Parallel Scavenge)

Serial 串行收集器

开启-XX:+UseSerialGC后,Young区使用SerialOld区使用Serial Old收集器组合。新生代、老年代都使用串行收集器,新生代使用复制算法,老年代使用标记-整理算法。

[GC (Allocation Failure) [DefNew: 2724K->319K(3072K), 0.0030656 secs] 2724K->923K(9920K), 0.0071603 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [DefNew: 2669K->255K(3072K), 0.0020595 secs] 3273K->1689K(9920K), 0.0021047 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 2351K->0K(3072K), 0.0014336 secs] 3785K->2711K(9920K), 0.0014814 secs] [Times: user=0.00 sys=0.02, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 1074K->0K(3072K), 0.0011529 secs] 3786K->3733K(9920K), 0.0011891 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 2096K->0K(3072K), 0.0019686 secs] 5829K->5776K(9920K), 0.0020058 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 2096K->2096K(3072K), 0.0000282 secs][Tenured: 5776K->2836K(6848K), 0.0033212 secs] 7873K->2836K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0041092 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 2096K->0K(3072K), 0.0008828 secs][Tenured: 4880K->3858K(6848K), 0.0036220 secs] 4933K->3858K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0045781 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [Tenured: 3858K->3708K(6848K), 0.0036932 secs] 3858K->3708K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0037427 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 def new generation   total 3072K, used 163K [0x00000000ff600000, 0x00000000ff950000, 0x00000000ff950000)
  eden space 2752K,   5% used [0x00000000ff600000, 0x00000000ff628f98, 0x00000000ff8b0000)
  from space 320K,   0% used [0x00000000ff8b0000, 0x00000000ff8b0000, 0x00000000ff900000)
  to   space 320K,   0% used [0x00000000ff900000, 0x00000000ff900000, 0x00000000ff950000)
 tenured generation   total 6848K, used 3708K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000)
   the space 6848K,  54% used [0x00000000ff950000, 0x00000000ffcef1f0, 0x00000000ffcef200, 0x0000000100000000)
 Metaspace       used 3509K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 384K, capacity 388K, committed 512K, reserved 1048576K

Parallel 并行收集器

开启-XX:+UseParNewGC后,Young区使用ParNewOld区使用Serial Old收集器组合。新生代使用并行收集器,老年代使用串行收集器,新生代使用复制算法,老年代使用标记-整理算法。

-XX:ParallelGCThreads=N:限制GC线程数量,默认开启与CPU数目相同的线程数量:

  • CPU>8 -> N=5/8
  • CPU<8 -> N=实际个数
[GC (Allocation Failure) [ParNew: 2683K->320K(3072K), 0.0021508 secs] 2683K->903K(9920K), 0.0022276 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2382K->179K(3072K), 0.0013619 secs] 2965K->1776K(9920K), 0.0014084 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2912K->162K(3072K), 0.0019345 secs] 4510K->3994K(9920K), 0.0019836 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2896K->124K(3072K), 0.0009408 secs] 6729K->4851K(9920K), 0.0009860 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2859K->2859K(3072K), 0.0000299 secs][Tenured: 4726K->3582K(6848K), 0.0043930 secs] 7586K->3582K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0045039 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Allocation Failure) [Tenured: 3582K->3329K(6848K), 0.0042125 secs] 3582K->3329K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0042616 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 par new generation   total 3072K, used 108K [0x00000000ff600000, 0x00000000ff950000, 0x00000000ff950000)
  eden space 2752K,   3% used [0x00000000ff600000, 0x00000000ff61b340, 0x00000000ff8b0000)
  from space 320K,   0% used [0x00000000ff8b0000, 0x00000000ff8b0000, 0x00000000ff900000)
  to   space 320K,   0% used [0x00000000ff900000, 0x00000000ff900000, 0x00000000ff950000)
 tenured generation   total 6848K, used 3329K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000)
   the space 6848K,  48% used [0x00000000ff950000, 0x00000000ffc90568, 0x00000000ffc90600, 0x0000000100000000)
 Metaspace       used 3509K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 384K, capacity 388K, committed 512K, reserved 1048576K

Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release

Parallel Scavenge 收集器

吞吐量优先的收集器。串行收集器在新生代和老年代的并行化。

自适应调节策略:虚拟机会根据当前系统运行情况收集性能监控信息,动态调整这些参数以提供最适合的停顿时间(-XX:MaxGCPauseMillis)或最大的吞吐量

-XX:+ParallelGC-XX:+UseParallelOldGC 可互相激活,使用Parallel Scavenge收集器

[GC (Allocation Failure) [PSYoungGen: 2042K->504K(2560K)] 2042K->704K(9728K), 0.0047040 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2390K->504K(2560K)] 2590K->1349K(9728K), 0.0011153 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1565K->504K(2560K)] 2411K->2641K(9728K), 0.0017143 secs] [Times: user=0.03 sys=0.02, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2089K->456K(2560K)] 4226K->3097K(9728K), 0.0014780 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2007K->504K(2560K)] 6664K->5161K(9728K), 0.0008853 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1551K->488K(1536K)] 6209K->6153K(8704K), 0.0016265 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 488K->0K(1536K)] [ParOldGen: 5665K->1671K(7168K)] 6153K->1671K(8704K), [Metaspace: 3476K->3476K(1056768K)], 0.0078707 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 1024K->0K(2048K)] 4711K->3687K(9216K), 0.0004365 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 20K->0K(2048K)] 3707K->3687K(9216K), 0.0003695 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 3687K->3687K(9216K), 0.0003840 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 3687K->3686K(7168K)] 3687K->3686K(9216K), [Metaspace: 3477K->3477K(1056768K)], 0.0084395 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 3686K->3686K(9216K), 0.0006912 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 3686K->3667K(7168K)] 3686K->3667K(9216K), [Metaspace: 3477K->3477K(1056768K)], 0.0082168 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 2048K, used 61K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 1024K, 5% used [0x00000000ffd00000,0x00000000ffd0f420,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 7168K, used 3667K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 51% used [0x00000000ff600000,0x00000000ff994c78,0x00000000ffd00000)
 Metaspace       used 3507K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 384K, capacity 388K, committed 512K, reserved 1048576K

CMS 收集器

CMS并发标记清除:并发收集低停顿,并发指的是与用户线程一起执行。

CMS适合堆内存大,CPU核数多的服务端应用。

开启-XX:+ConcMarkSweepGC,会自动将-XX:+UseParNewGC打开。

Young区使用ParNewOld区使用CMS+Serial Old的收集组合,Serial Old将作为CMS出错后的后备收集器。

四步过程

  • 初始标记CMS initial mark:会STW。只是标记一下GC Roots能直接关联的对象,速度很快,仍然需要暂停所有工作线程。
  • 并发标记CMS concurrent mark:和用户线程一起。进行GC Roots跟踪过程,和用户线程一起,不需要暂停工作线程。主要标记过程,标记全部对象。
  • 重新标记CMS remark:会STW。修正在并发标记初期,因用户程序继续运行而导致标记产生变动的一部分对象的标记记录,仍然需要暂停所有工作线程。由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正。
  • 并发清除CMS concurrent sweep:和用户线程一起。清除GC Roots不可达对象。基于标记结果,直接清除对象。

优点

并发收集停顿低。

缺点

  1. 并发执行,对CPU资源压力大。由于并发进行,CMS在收集与应用线程会同时增加对堆内存的占用,也就是说,CMS必须要在老年代堆内存用尽之前完成垃圾回收,否则CMS回收失败时,将触发担保机制,串行老年代收集器将会以STW的方式进行一次GC,从而造成较大停顿时间。
  2. 采用标记清除算法会导致大量碎片。标记清除算法无法整理空间碎片,老年代空间会随着应用时长被逐步耗尽,最后将不得不通过担保机制对堆内存进行压缩。CMS也提供了参数-XX:CMSFullGCsBeforeCompaction来指定多少次CMS收集之后,进行一次压缩的Full GC(默认0,即每次都进行内存整理)。
[GC (Allocation Failure) [ParNew: 2714K->320K(3072K), 0.0029990 secs] 2714K->910K(9920K), 0.0031040 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2683K->287K(3072K), 0.0013594 secs] 3273K->1825K(9920K), 0.0014302 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2353K->186K(3072K), 0.0010001 secs] 3892K->2732K(9920K), 0.0010569 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 1246K->163K(3072K), 0.0010564 secs] 3792K->3716K(9920K), 0.0011046 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (CMS Initial Mark) [1 CMS-initial-mark: 3553K(6848K)] 5731K(9920K), 0.0002121 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-mark-start]
[GC (Allocation Failure) [ParNew: 2230K->158K(3072K), 0.0018765 secs] 5784K->5726K(9920K), 0.0019204 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-mark: 0.002/0.004 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (CMS Final Remark) [YG occupancy: 1165 K (3072 K)][Rescan (parallel) , 0.0001963 secs][weak refs processing, 0.0000243 secs][class unloading, 0.0004621 secs][scrub symbol table, 0.0007053 secs][scrub string table, 0.0002014 secs][1 CMS-remark: 5568K(6848K)] 6733K(9920K), 0.0017438 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-sweep-start]
[GC (Allocation Failure) [ParNew: 2225K->2225K(3072K), 0.0000333 secs][CMS[CMS-concurrent-sweep: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
 (concurrent mode failure): 4936K->2683K(6848K), 0.0047620 secs] 7162K->2683K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0048994 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 2123K->2123K(3072K), 0.0000303 secs][CMS: 6712K->5705K(6848K), 0.0055040 secs] 8835K->5705K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0056218 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (CMS Initial Mark) [1 CMS-initial-mark: 5705K(6848K)] 7719K(9920K), 0.0001604 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (CMS Final Remark) [YG occupancy: 2014 K (3072 K)][Rescan (parallel) , 0.0002347 secs][weak refs processing, 0.0000107 secs][class unloading, 0.0004198 secs][scrub symbol table, 0.0007509 secs][scrub string table, 0.0001967 secs][1 CMS-remark: 5705K(6848K)] 7719K(9920K), 0.0017557 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-sweep-start]
[GC (Allocation Failure) [ParNew: 2068K->2068K(3072K), 0.0000265 secs][CMS[CMS-concurrent-sweep: 0.000/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
 (concurrent mode failure): 5705K->2682K(6848K), 0.0047249 secs] 7773K->2682K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0048367 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [ParNew: 2068K->2068K(3072K), 0.0000294 secs][CMS: 6712K->6712K(6848K), 0.0046618 secs] 8781K->6712K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0047740 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Allocation Failure) [CMS: 6712K->6692K(6848K), 0.0053542 secs] 6712K->6692K(9920K), [Metaspace: 3478K->3478K(1056768K)], 0.0054140 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (CMS Initial Mark) [1 CMS-initial-mark: 6692K(6848K)] 6692K(9920K), 0.0001758 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (CMS Final Remark) [YG occupancy: 54 K (3072 K)][Rescan (parallel) , 0.0001920 secs][weak refs processing, 0.0000098 secs][class unloading, 0.0003725 secs][scrub symbol table, 0.0006426 secs][scrub string table, 0.0001899 secs][1 CMS-remark: 6692K(6848K)] 6746K(9920K), 0.0015437 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-reset-start]
[CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 par new generation   total 3072K, used 109K [0x00000000ff600000, 0x00000000ff950000, 0x00000000ff950000)
  eden space 2752K,   3% used [0x00000000ff600000, 0x00000000ff61b688, 0x00000000ff8b0000)
  from space 320K,   0% used [0x00000000ff900000, 0x00000000ff900000, 0x00000000ff950000)
  to   space 320K,   0% used [0x00000000ff8b0000, 0x00000000ff8b0000, 0x00000000ff900000)
 concurrent mark-sweep generation total 6848K, used 6692K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 3509K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 384K, capacity 388K, committed 512K, reserved 1048576K

收集器的选择

  • CPU或小内存,单机程序:-XX:+UseSerialGC
  • CPU,需要最大吞吐量,后台计算型应用:-XX:+UseParallelGC或者-XX:+UseParallelOldGC
  • CPU,追求低停顿时间,需要快速响应,如互联网应用:-XX:+UseConcMarkSweepGC
阅读 476 · 发布于 2022-05-31

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批