從今天開始,我會發5個關於java虛擬機的小系列:
實戰Java虛擬機之一「堆溢出處理」
[實戰Java虛擬機之二「虛擬機的工做模式」][2]
[實戰Java虛擬機之三「G1的新生代GC」][3]
實戰Java虛擬機之四「禁用System.gc()」
實戰Java虛擬機之五「開啓JIT編譯」java
下面說說【實戰Java虛擬機之一「堆溢出處理」】數組
在Java程序的運行過程當中,若是堆空間不足,則有可能拋出內存溢出錯誤(Out Of Memory),簡稱爲OOM。以下文字顯示了典型的堆內存溢出:性能優化
Exception in thread 「main」 java.lang.OutOfMemoryError: Java heap space at geym.zbase.ch3.heap.DumpOOM.main(DumpOOM.java:20)
一旦發生這類問題,系統就會被迫退出。若是發生在生產環境,可能會引發嚴重的業務中斷。爲了可以不斷改善系統,避免或減小這類錯誤的發生,須要在發生錯誤時,得到儘量多的現場信息,以幫助研發人員排查現場問題。Java虛擬機提供了參數-XX:+HeapDumpOnOutOfMemoryError,使用該參數,能夠在內存溢出時導出整個堆信息。和它配合使用的還有-XX:HeapDumpPath,能夠指定導出堆的存放路徑。
【示例3-4】如下代碼合計分配了25M內存空間。jvm
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)文件。spa
這裏給出一個在發生OOM時導出線程轉存的例子。準備printstack.bat腳本以下:線程
D:/tools/jdk1.7_40/bin/jstack -F %1 > D:/a.txt
以上腳本將會導出給定Java虛擬機進程的線程信息,並保存在D:/a.txt文件中。
使用以下參數執行上述代碼:code
-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目錄,進行嘗試。
節選自