1.Full GC
在使用CMS的情况下,如果出现promotion failed或者concurrent mode failure,会触发Full GC。
下边通过代码来演示一下。
(1)promotion failed,代码如下:
public static void main(String[] args) throws Exception {
BigObj o1 = new BigObj(1024 * 1024 * 2);
BigObj o2 = new BigObj(1024 * 1024 * 2);
BigObj o3 = new BigObj(1024 * 1024 * 2);
System.out.println(">>> minor gc");
BigObj o4 = new BigObj(1024 * 1024 * 2);
TimeUnit.SECONDS.sleep(2);
BigObj o5 = new BigObj(1024 * 1024 * 2);
BigObj o6 = new BigObj(1024 * 1024 * 2);
System.out.println(">>> promotion failed");
BigObj o7 = new BigObj(1024 * 1024 * 2);
TimeUnit.SECONDS.sleep(2);
}
private static class BigObj {
private byte[] b;
public BigObj(int c) {
b = new byte[c];
}
}
参数:
-Xms20m -Xmx20m -Xmn10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCMSInitiatingOccupancyOnly
我用的是sun JDK 1.6.0 u30 64位
在输出的日志中可以看到:
[GC 2.094: [ParNew: 6578K->6578K(9216K), 0.0000323 secs]2.094: [CMS: 6150K->8192K(10240K), 0.0145035 secs] 12728K->12449K(19456K), [CMS Perm : 3058K->3057K(21248K)], 0.0146291 secs] [Times: user=0.00 sys=0.02, real=0.01 secs]
(2)concurrent mode failure,代码同上,将参数改为:
-Xms20m -Xmx20m -Xmn10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
在日志中可以看到:
[GC 2.105: [ParNew: 6562K->6562K(9216K), 0.0000330 secs]2.105: [CMS2.108: [CMS-concurrent-mark: 0.004/0.004 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
(concurrent mode failure): 6150K->8192K(10240K), 0.0173765 secs] 12712K->12449K(19456K), [CMS Perm : 3058K->3057K(21248K)], 0.0175193 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
2.preclean
CMS GC在remark之前有个concurrent abortable preclean的阶段。
当Eden的占用超过2M时,执行此阶段,一直持续到Eden的占用超过50%时,才触发remark。当然也不会一直持续下去,如果超过5000毫秒Eden的占用仍未超过50%时,也会结束此阶段,开始触发remark。这3个参数可以通过-XX:CMSScheduleRemarkEdenSizeThreshold -XX:CMSScheduleRemarkEdenPenetration -XX:CMSMaxAbortablePrecleanTime 分别进行设置。
(1)Eden占用不超过2M的情况:
代码如下:
public static void main(String[] args) throws Exception {
BigObj o1 = new BigObj(1024 * 1024 * 2);
BigObj o2 = new BigObj(1024 * 1024 * 2);
BigObj o3 = new BigObj(1024 * 1024 * 3);
System.out.println(">>> minor gc");
BigObj o4 = new BigObj(1024 * 1024 * 1);
TimeUnit.SECONDS.sleep(2);
}
参数:
-Xms20m -Xmx20m -Xmn10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
在日志中可以看到:
2.116: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2.116: [GC[YG occupancy: 1615 K (9216 K)]2.116: [Rescan (parallel) , 0.0001575 secs]2.117: [weak refs processing, 0.0000058 secs] [1 CMS-remark: 7174K(10240K)] 8790K(19456K), 0.0002273 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
(2)Eden的占用超过50%:
代码如下:
public static void main(String[] args) throws Exception {
BigObj o1 = new BigObj(1024 * 1024 * 2);
BigObj o2 = new BigObj(1024 * 1024 * 2);
BigObj o3 = new BigObj(1024 * 1024 * 2);
System.out.println(">>> minor gc");
BigObj o4 = new BigObj(1024 * 1024 * 2);
TimeUnit.SECONDS.sleep(2);
BigObj o5 = new BigObj(1024 * 1024 * 3);
TimeUnit.SECONDS.sleep(2);
}
参数同上:
在日志中可以看到:
2.106: [CMS-concurrent-abortable-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2.106: [GC[YG occupancy: 5546 K (9216 K)]2.106: [Rescan (parallel) , 0.0001678 secs]2.106: [weak refs processing, 0.0000058 secs] [1 CMS-remark: 6150K(10240K)] 11696K(19456K), 0.0002596 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
(3)Eden的占用仍未超过50%,持续时间超过5000毫秒:
代码如下:
public static void main(String[] args) throws Exception {
BigObj o1 = new BigObj(1024 * 1024 * 2);
BigObj o2 = new BigObj(1024 * 1024 * 2);
BigObj o3 = new BigObj(1024 * 1024 * 2);
System.out.println(">>> minor gc");
BigObj o4 = new BigObj(1024 * 1024 * 2);
TimeUnit.SECONDS.sleep(2);
BigObj o5 = new BigObj(1024 * 1024 * 1);
TimeUnit.SECONDS.sleep(7);
}
参数同上:
在日志中可以看到:
CMS: abort preclean due to time 7.210: [CMS-concurrent-abortable-preclean: 0.076/5.093 secs] [Times: user=0.02 sys=0.00, real=5.10 secs]
7.210: [GC[YG occupancy: 3498 K (9216 K)]7.210: [Rescan (parallel) , 0.0002051 secs]7.210: [weak refs processing, 0.0000054 secs] [1 CMS-remark: 6150K(10240K)] 9648K(19456K), 0.0002727 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
如果增加参数:-XX:CMSMaxAbortablePrecleanTime=3000
日志变为:
CMS: abort preclean due to time 5.127: [CMS-concurrent-abortable-preclean: 0.044/3.024 secs] [Times: user=0.01 sys=0.00, real=3.02 secs]
5.127: [GC[YG occupancy: 3498 K (9216 K)]5.127: [Rescan (parallel) , 0.0001886 secs]5.127: [weak refs processing, 0.0000058 secs] [1 CMS-remark: 6150K(10240K)] 9648K(19456K), 0.0002634 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
另外我试了一下CMSScheduleRemarkEdenPenetration参数貌似不管用啊