從今天開始,我會發5個關於java虛擬機的小系列:java
下面說說【實戰Java虛擬機之一「堆溢出處理」】性能
在Java程序的運行過程當中,若是堆空間不足,則有可能拋出內存溢出錯誤(Out Of Memory),簡稱爲OOM。以下文字顯示了典型的堆內存溢出:
Exception in thread 「main」 java.lang.OutOfMemoryError: Java heap space spa
at geym.zbase.ch3.heap.DumpOOM.main(DumpOOM.java:20) .net
一旦發生這類問題,系統就會被迫退出。若是發生在生產環境,可能會引發嚴重的業務中斷。爲了可以不斷改善系統,避免或減小這類錯誤的發生,須要在發生錯誤時,得到儘量多的現場信息,以幫助研發人員排查現場問題。Java虛擬機提供了參數-XX:+HeapDumpOnOutOfMemoryError,使用該參數,能夠在內存溢出時導出整個堆信息。和它配合使用的還有-XX:HeapDumpPath,能夠指定導出堆的存放路徑。
【示例3-4】如下代碼合計分配了25M內存空間。
public class DumpOOM {
public static void main(String[] args) {
Vector v=new Vector();
for(int i=0;i<25;i++)
v.add(new byte[1*1024*1024]);
}
}
使用以下參數執行上述代碼:
-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump
顯然20M堆空間不足以容納25M內存,系統好比發生內存溢出,在發生錯誤後,控制檯輸出以下:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to d:/a.dump …
Heap dump file created [23067302 bytes in 0.160 secs]
Exception in thread 「main」 java.lang.OutOfMemoryError: Java heap space
at geym.zbase.ch3.heap.DumpOOM.main(DumpOOM.java:19)
能夠看到,虛擬機將當前的堆導出,並保存到D:/a.dump文件下。使用MAT等工具打開該文件進行分析,如圖所示,能夠很容易地找到這些byte數組和保存它們的Vector對象實例。有關MAT等工具的使用,能夠參閱《實戰Java虛擬機-jvm故障診斷與性能優化》第7章。
除了在發生OOM時能夠導出堆信息外,虛擬機還容許在發生錯誤時執行一個腳本文件。該文件能夠用於奔潰程序的自救、報警或者通知,也能夠幫助開發人員得到更多的系統信息,如完整的線程轉存(即Thread Dump或者Core Dump)文件。
這裏給出一個在發生OOM時導出線程轉存的例子。準備printstack.bat腳本以下:
D:/tools/jdk1.7_40/bin/jstack -F %1 > D:/a.txt
以上腳本將會導出給定Java虛擬機進程的線程信息,並保存在D:/a.txt文件中。
使用以下參數執行上述代碼:
-Xmx20m -Xms5m 「-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p」 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump
在程序異常退出時,系統D盤下會生成新文件a.txt,裏面保存着線程轉存信息。本例中,文件路徑「D:/tools/jdk1.7_40」爲筆者的JDK按照目錄,讀者能夠替換成本身的JAVA_HOME目錄,進行嘗試。
《實戰Java虛擬機》一書Q交流羣:397196583