关于JDK6和JDK7的GC

miroku 2013-08-29

/**
 * VM参数:-Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails
 */
public class MinorGC {

	private static final int _1MB = 1024 * 1024;

	public static void testAllocation() {
		byte[] allocation1, allocation2, allocation3, allocation4;
		allocation1 = new byte[2 * _1MB];
		allocation2 = new byte[2 * _1MB];
		allocation3 = new byte[2 * _1MB];
		allocation4 = new byte[4 * _1MB]; // 出现一次Minor GC
	}
	public static void main(String[] args) {
		testAllocation();
	}
}

以上代码在执行的时候,在JDK7和JDK6上有不同的表现。我测试了JDK6 32位client模式,JDK7 64位client模式  JDK764位server模式,在JDK7-64位(无论client还是server)下GC日志如下:
Heap
 PSYoungGen      total 9216K, used 6980K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 85% used [0x00000000ff600000,0x00000000ffcd1048,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)
 PSPermGen       total 21248K, used 2526K [0x00000000f9a00000, 0x00000000faec0000, 0x00000000fec00000)
  object space 21248K, 11% used [0x00000000f9a00000,0x00000000f9c779e8,0x00000000faec0000)

而在JDK6 32位client下,会进行一次Minor GC。据有的同学测试在JDK6-64位上表现和JDK7-64位是一样的。所以想问下:是不是JDK6和JDK7的GC策略有变化,使得在JDK7时,不进行Minor GC,而直接把4M的数组在老年代分配了?
RednaxelaFX 2013-08-29
miroku 写道
所以想问下:是不是JDK6和JDK7的GC策略有变化,使得在JDK7时,不进行Minor GC,而直接把4M的数组在老年代分配了?

不是。

您用的所谓JDK7 64位Client VM,多半实际上是Server VM来的。Oracle JDK并没有发布64位的Client VM,而只有Server VM。
您试试在所谓JDK7 64位Client VM上执行这个:
java -client -version

然后把结果贴出来看看~

实际上您看到的区别就是Client VM跟Server VM默认用的GC堆不同带来的。
Client VM默认用Serial GC,Server VM默认用Parallel GC。后者有直接把大对象分配在old gen的逻辑,而前者没启动同类逻辑。仅此而已。

另外请参考之前一帖的分析方法:http://hllvm.group.iteye.com/group/topic/38293
miroku 2013-08-29
果然如此,多谢大神

java -client -version 
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
yasenagat 2013-09-02
RednaxelaFX 写道
miroku 写道
所以想问下:是不是JDK6和JDK7的GC策略有变化,使得在JDK7时,不进行Minor GC,而直接把4M的数组在老年代分配了?

不是。

您用的所谓JDK7 64位Client VM,多半实际上是Server VM来的。Oracle JDK并没有发布64位的Client VM,而只有Server VM。
您试试在所谓JDK7 64位Client VM上执行这个:
java -client -version

然后把结果贴出来看看~

实际上您看到的区别就是Client VM跟Server VM默认用的GC堆不同带来的。
Client VM默认用Serial GC,Server VM默认用Parallel GC。后者有直接把大对象分配在old gen的逻辑,而前者没启动同类逻辑。仅此而已。

另外请参考之前一帖的分析方法:http://hllvm.group.iteye.com/group/topic/38293


试了一下,发现
Serial GC设置了-XX:PretenureSizeThreshold=3145728后,只要对象超过这个大小,
不管eden是否还有足够大的剩余,都把超过3M的对象放到old
Paralle,设置次参数应该无效,当eden空间不足时,才会把大对象直接放到old,不进行minor gc
Global site tag (gtag.js) - Google Analytics