看看以下程序?
?
class="java" name="code">public class YoungGC { public static void main(String[] args) { long i = 0; long start = System.currentTimeMillis(); while (true) { int length = 1; for (int j = 0; j < length; j++) { byte[] x = new byte[1024]; } i++; if (i % 1000 == 0) { if (System.currentTimeMillis() > start + 30000) { break; } } } } }
?
?
以如下参数运行 java -Xms1G -Xmx1G -Xmn512m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -cp . YoungGC,会在console中看到如下的GC输出,持续30s。
11.285: [GC [PSYoungGen: 2096640K->0K(2096960K)] 2096800K->160K(4194112K), 0.0010110 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]?
11.769: [GC [PSYoungGen: 2096768K->0K(2096960K)] 2096928K->160K(4194112K), 0.0029880 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]?
12.257: [GC [PSYoungGen: 2096768K->0K(2096960K)] 2096928K->160K(4194112K), 0.0009180 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]?
?
然后让我们把临时变量的大小从1024改成64,再次重跑以下程序,你看见了什么?
public class YoungGC {
public static void main(String[] args) {
long i = 0;
long start = System.currentTimeMillis();
while (true) {
int length = 1;
for (int j = 0; j < length; j++) {
byte[] x = new byte[64];
}
i++;
if (i % 1000 == 0) {
if (System.currentTimeMillis() > start + 30000) {
break;
}
}
}
}
}
?
?
我在 hotspot jdk 1.7.0_21测试的结果都是 什么都没看见!完全没有GC,用jvisualvm连上线程后会发现young gen size根本没有变,而如果 把64改成 65,则GC又出现了。
换到jdk 1.6.0_21下就没有这种问题,即使临时变量的大小是1也会出现GC。
byte[64] 正好是64位下的一个word,看起来hotspot jvm 在1.7的对于一些小对象作了重用?
?
补充:
这个变化貌似是从1.6.0_23的Java Hotspot VM 19.0引入的,但是没找到具体说明。。。
?