持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
收集步骤方法二
CMS收集器收集步骤,以下是将上面的四个步骤进一步细分为7个步骤,但是其中有stw的还是只有两个步骤,减少了stw的时间。
-
Phase 1: Initial Mark,这个是CMS两次stop-the-world事件的其中一次,这个阶段的目标是:标记那些直接被GCroot引用或者被年轻代存活对象所引用的所有对象(CMS是针对老年代的)
-
Phase 2:Concurrent Mark,在这个阶段 Garbage Collector会遍历老年代,然后标记所有存活的对象,它会根据上个阶段找到的 GC Roots遍历査找。并发标记阶段,它会与用户的应用程序并发运行并不是老年代所有的存活对象都会被标记,因为在标记期间用户的程序可能会改变一些引用。在下的图中,与阶段1的图进行对比,就会发现有一个对象的引用已经发生了变化
-
Phase 3: Concurrent Preclean,这也是一个并发阶段,与应用的线程并发运行,并不会stop用户线程。在并发运行的过程中,一些对象的引用可能会发生变化,但是这种情况发生时,JVM会将包含这个对象的区域(Card)标记为Diy,这个动作称为Card Marking,在pre-clean阶段,那些能够从Dirty对象到达的对象也会被标记,这个标记做完之后, dirty card标记就会被清除了
-
Phase 4: Concurrent Abortable Preclean,这也是一个并发阶段,但是同样不会影响用户的应用线程,这个阶段是为了尽量承担STW(stop-the-world)中最终标记阶段的工作。这个阶段持续时间依赖于很多的因素由于这个阶段是在重复做很多相同的工作(比如:重复迭代的次数、完成的工作量或者时钟时间等)
-
Phase 5: Final Remark,这是第二个STW阶段,也是CMS中的最后一个,这个阶段的目标是标记老年代所有的存活对象,由于之前的阶段是并发执行的,GC线程可能跟不上应用程序的变化为了完成标记老年代所有存活对象的目标,STW就非常有必要了,这个阶段会比前面的几个阶段更复杂一些
-
Phase 6: Concurrent Sweep,这里不需要STW,它是与用户的应用程序并发运行,这个阶段是:清除那些不再使用的对象,回收它们的占用空间为将来使用
-
Phase 7: Concurrent Reset,这个阶段也是并发执行的,它会重设CMS内部的数据结构,为下次的GC做准备
实验
实验代码MyTest5.java
虚拟机参数
- -verbose:gc -Xmx20M -Xms20m -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC
输出结果
111111
[GC (Allocation Failure) [ParNew: 6104K->742K(9216K), 0.0029166 secs] 6104K->4840K(19456K), 0.0029703 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2222222
[GC (Allocation Failure) [ParNew: 4995K->65K(9216K), 0.0034135 secs] 9093K->8973K(19456K), 0.0034413 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 8907K(10240K)] 13069K(19456K), 0.0001747 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
# CMS-initial-mark
[CMS-concurrent-mark-start]
33333333
4444444
[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]
[CMS-concurrent-abortable-preclean-start]
[CMS-concurrent-abortable-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Final Remark) [YG occupancy: 6531 K (9216 K)][Rescan (parallel) , 0.0001118 secs][weak refs processing, 0.0000169 secs][class unloading, 0.0003630 secs][scrub symbol table, 0.0006629 secs][scrub string table, 0.0001339 secs][1 CMS-remark: 8907K(10240K)] 15439K(19456K), 0.0013879 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
par new generation total 9216K, used 6531K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) eden space 8192K, 78% used [0x00000000fec00000, 0x00000000ff250980, 0x00000000ff400000) # 新生代存了一个4m和一个2m的数组对象,大概是6m from space 1024K, 6% used [0x00000000ff400000, 0x00000000ff4104c8, 0x00000000ff500000)[CMS-concurrent-sweep-start]
to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) concurrent mark-sweep generation total 10240K, used 8907K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) # 老年代里面是存了两个4m的数组对象,大概是8m Metaspace used 3239K, capacity 4496K, committed 4864K, reserved 1056768K class space used 352K, capacity 388K, committed 512K, reserved 1048576K