jvm的gc log 以及各种参数

-XX:NewRatio=1

 表示新生代占1,老年代占1。则新生代占整个堆的1/2(这个参数一般不会使用)

-XX:SurvivorRatio=8 

表示Eden:Survivor=8:1
-Xms20m表示堆空间初始大小为 20 M
-Xmx20m表示堆空间最大大小为 20 M
-Xmn10m表示新生代大小为 10M
-XX:+UseParNewGC表示年轻代使用serial的多线程版本,它是server模式下首选的新生代收集器,因为能与cms配合(我们生产也是这么配的)
-XX:+UseConcMarkSweepGC

表示老年代用cms收集器(我们生产也是这么配置的)

-XX:+PrintGC

简单打印gc日志

-XX:+PrintGCDetails详细打印gc日志

测试代码

我们两次分配了 4M 的内存空间,人为制造 GC。

/**
 * @author 陈树义
 * @date 2018.09.29
 */
public class GCDemo {
    public static void main(String[] args) {
        // allocate 4M space
        byte[] b = new byte[4 * 1024 * 1024];
        System.out.println("first allocate");
        // allocate 4M space
        b = new byte[4 * 1024 * 1024];
        System.out.println("second allocate");
    }
}

打印gc日志

-XX:+UseParNewGC 
-XX:+UseConcMarkSweepGC 
-Xms20M -Xmx20M -Xmn10M 
-XX:NewRatio=1 
-XX:+PrintGC

年轻代用ParNew,老年代用cms,初始堆大小20M,最大堆大小20M,年轻代10M,老年代:年轻代=1:1,详细打印gc日志

Connected to the target VM, address: '127.0.0.1:51295', transport: 'socket'


[GC (Allocation Failure) [ParNew: 8174K->766K(9216K), 0.0007652 secs] 8174K->766K(19456K), 0.0011366 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 8958K->1024K(9216K), 0.0027190 secs] 8958K->2198K(19456K), 0.0028090 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 9216K->1024K(9216K), 0.0018645 secs] 10390K->3232K(19456K), 0.0019519 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [ParNew: 8123K->651K(9216K), 0.0006875 secs] 10331K->2860K(19456K), 0.0007580 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 


first allocate


[GC (Allocation Failure) [ParNew: 4906K->343K(9216K), 0.0054465 secs] 7114K->6942K(19456K), 0.0054800 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 


[GC (CMS Initial Mark) [1 CMS-initial-mark: 6598K(10240K)] 11038K(19456K), 0.0002575 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 


[CMS-concurrent-mark-start]
second allocate
[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.02 sys=0.01, 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: 4760 K (9216 K)][Rescan (parallel) , 0.0002340 secs][weak refs processing, 0.0000967 secs][class unloading, 0.0004217 secs][scrub symbol table, 0.0004282 secs][scrub string table, 0.0001068 secs][1 CMS-remark: 6598K(10240K)] 11359K(19456K), 0.0014357 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.001/0.001 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 9216K, used 4842K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  54% used [0x00000000fec00000, 0x00000000ff064a10, 0x00000000ff400000)
  from space 1024K,  33% used [0x00000000ff500000, 0x00000000ff555f40, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 concurrent mark-sweep generation total 10240K, used 6198K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 5104K, capacity 5316K, committed 5504K, reserved 1056768K
  class space    used 581K, capacity 627K, committed 640K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:51295', transport: 'socket'

Process finished with exit code 0

Young GC部分

  1. GC:区别MinorGC和FullGC的标识,这次代表的是MinorGC
  2. Allocation Failure:MinorGC的原因,在这个case里边,由于年轻代不满足申请的空间,因此触发了MinorGC
  3. ParNew: 8174K->766K(9216K), 0.0007652 secs:经过ParNew收集器的收集,收集前8174K,收集后766K,年轻代大小为9126K,耗时0.0007652秒
  4. 8174K->766K(19456K), 0.0011366 secs:经过ParNew收集器的收集,收集前8174K,收集后766K,整个堆的大小为19456K,耗时0.0011366秒

FULL GC部分

CMS Initial Mark(阶段1):cms的初始标记,需要stop the world。收集所有GC root 和 被年轻代存活对象直接引用的老年代对象。

CMS-initial-mark: 6598K(10240K):当前老年代被使用了6598K,老年代大小为10240K

11038K(19456K):当前整个堆被使用了11038K,整个堆的大小为19456K

Concurrent Mark(阶段2) :并发标记。会从找到的GC Root开始,找到老年代中存活的对象。并不是老年代中所有存活的对象都会被标记,必须得从GC root出发的才能被标记。不会stop the world。

 Concurrent Preclean

这个阶段又是一个并发阶段,和应用线程并行运行,不会中断他们。前一个阶段在并行运行的时候,一些对象的引用已经发生了变化,当这些引用发生变化的时候,JVM会标记堆的这个区域为Dirty Card(包含被标记但是改变了的对象,被认为"dirty"),这就是 Card Marking。那些能够从dirty card对象到达的对象也会被标记,这个标记做完之后,dirty card标记就会被清除了。

Concurrent Abortable Preclean

Final Remark

这个阶段是CMS中第二个并且是最后一个STW的阶段。该阶段的任务是完成标记整个年老代的所有的存活对象。由于之前的预处理是并发的,它可能跟不上应用程序改变的速度,这个时候,STW是非常需要的来完成这个严酷考验的阶段。

通常CMS尽量运行Final Remark阶段在年轻代是足够干净的时候,目的是消除紧接着的连续的几个STW阶段。

1

1

1

1

1

1

1

1