gc報告的閱讀
首先我們看一條gc報告
D:\雜項\java>java -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:SurvivorRatio=8 testAllocation
[GC[DefNew: 7492K->980K(9216K), 0.0034913 secs] 7492K->7124K(19456K), 0.0037735 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 3358K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
eden space 8192K, 29% used [0x00000000f9a00000, 0x00000000f9c52728, 0x00000000fa200000)
from space 1024K, 95% used [0x00000000fa300000, 0x00000000fa3f5100, 0x00000000fa400000)
to space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
tenured generation total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
the space 10240K, 60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
compacting perm gen total 21248K, used 2471K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 11% used [0x00000000fae00000, 0x00000000fb069d58, 0x00000000fb069e00, 0x00000000fc2c0000)
No shared spaces configured.
先看java運作的幾個參數
-Xms20m -Xmx20m -Xmn10m說明堆的大小固定不變,為20m,其中年輕代為10m
-XX:+PrintGCDetails 讓虛拟機列印出gc日志,最後輸出目前記憶體各個區域的使用情況。注意,這是兩部分内容,一個是gc日志,一個是記憶體使用情況。
-XX:+UseSerialGC 使用-XX:+UseSerialGC可以使用Serial+Serial Old模式運作進行記憶體回收(這也是虛拟機在Client模式下運作的預設值)
-XX:SurvivorRatio=8 說明eden區與一個Survivor區的大小比例為8。
至于[GC[DefNew: 7492K->980K(9216K), 0.0034913 secs] 7492K->7124K(19456K), 0.0037735 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]具體是什麼意思
大家參閱
Java GC 日志詳解
我就補充一點:
日志開頭的[GC和[Full GC說明了此次垃圾收集的停頓類型,而不是用來區分新生代GC還是老年代GC。
我們看幾個執行個體
D:\雜項\java>type testAllocation2.java
/**
*
* -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:SurvivorRatio=8
*
*/
public class testAllocation2{
private static int _1m=1024*1024;
public static void main(String[] args) {
byte[] all1,all2,all3,all4,all5;
all1=new byte[_1m * 2];
all2=new byte[_1m * 2];
all3=new byte[_1m * 2];
all4=new byte[_1m * 4];
}
}
D:\雜項\java>javac testAllocation2.java
D:\雜項\java>java -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:SurvivorRatio=8 testAllocation2
Heap
PSYoungGen total 9216K, used 7143K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 87% used [0x00000000ff600000,0x00000000ffcf9ff8,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 21504K, used 2468K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000)
object space 21504K, 11% used [0x00000000f9a00000,0x00000000f9c691d0,0x00000000faf00000)
D:\雜項\java>
上面的代碼是我從<<深入了解java虛拟機>>第二章中引過來的。但是并沒有發生gc呀?
花了好長時間,才知道得加上一個參數。
-XX:+UseSerialGC
不是說預設就是這個參數麼?
我的java版本:
D:\雜項\java>java -version
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
搞不清楚了。
我們加上這個參數
D:\雜項\java>java -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:SurvivorRatio=8 testAllocation2
[GC[DefNew: 6980K->468K(9216K), 0.0034679 secs] 6980K->6612K(19456K), 0.0037547 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4894K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
eden space 8192K, 54% used [0x00000000f9a00000, 0x00000000f9e527b0, 0x00000000fa200000)
from space 1024K, 45% used [0x00000000fa300000, 0x00000000fa3750f0, 0x00000000fa400000)
to space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
tenured generation total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
the space 10240K, 60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
compacting perm gen total 21248K, used 2471K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 11% used [0x00000000fae00000, 0x00000000fb069cf8, 0x00000000fb069e00, 0x00000000fc2c0000)
No shared spaces configured.
D:\雜項\java>
OK,發生gc了。
all1,all2,all3加入後,eden區域已經被占了6m了,本來就隻有8m,all4的4m一來,馬上就發生Minor gc
6m的對象中沒有任何一個能放入一個survivor區,那沒辦法了,6m的對象直接進入老年代。
tenured generation total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
the space 10240K, 60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
能說明這個問題。
那麼all4呢,它的4m,就還是放到eden區。
我們再看一個例子。
private static int _0_5M=1024*512;
public static void main(String[] args) {
byte[] all1,all2,all3,all4,all5;
all1=new byte[1*_0_5M];
all2=new byte[4*_0_5M];
all3=new byte[4*_0_5M];
all4=new byte[4*_0_5M];
all5=new byte[4*_0_5M];
}
結果
D:\雜項\java>java -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:SurvivorRatio=8 testAllocation
[GC[DefNew: 7492K->980K(9216K), 0.0036395 secs] 7492K->7124K(19456K), 0.0038973 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 3358K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
eden space 8192K, 29% used [0x00000000f9a00000, 0x00000000f9c52728, 0x00000000fa200000)
from space 1024K, 95% used [0x00000000fa300000, 0x00000000fa3f5100, 0x00000000fa400000)
to space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
tenured generation total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
the space 10240K, 60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
compacting perm gen total 21248K, used 2471K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 11% used [0x00000000fae00000, 0x00000000fb069d00, 0x00000000fb069e00, 0x00000000fc2c0000)
No shared spaces configured.
D:\雜項\java>
all5産生時發生了minor gc,與上面的例子不同的時,最後:all2,all3,all4進入了老年代,而all1與all5共2.5m進入了eden區。
那怎麼survivor還占用了95%,這個我估計是堆裡的其他資料。大家忽略之。