實戰Java虛擬機之一“堆溢出處理”


從今天開始,我會發5個關於java虛擬機的小系列:

下面說說【實戰Java虛擬機之一“堆溢出處理”】

在Java程序的運行過程中,如果堆空間不足,則有可能拋出內存溢出錯誤(Out Of Memory),簡稱為OOM。如下文字顯示了典型的堆內存溢出:

  1. Exception in thread “main” java.lang.OutOfMemoryError: Java heap space  
  2. at geym.zbase.ch3.heap.DumpOOM.main(DumpOOM.java:20)  


一旦發生這類問題,系統就會被迫退出。如果發生在生產環境,可能會引起嚴重的業務中斷。為了能夠不斷改善系統,避免或減少這類錯誤的發生,需要在發生錯誤時,獲得盡可能多的現場信息,以幫助研發人員排查現場問題。Java虛擬機提供了參數-XX:+HeapDumpOnOutOfMemoryError,使用該參數,可以在內存溢出時導出整個堆信息。和它配合使用的還有-XX:HeapDumpPath,可以指定導出堆的存放路徑。

 

【示例3-4】以下代碼合計分配了25M內存空間。


 
  1. public class DumpOOM {  
  2.  public static void main(String[] args) {  
  3.  Vector v=new Vector();  
  4.   for(int i=0;i<25;i++)  
  5.    v.add(new byte[1*1024*1024]);  
  6.  }  
  7. }  



 使用如下參數執行上述代碼:

-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump

顯然20M堆空間不足以容納25M內存,系統比如發生內存溢出,在發生錯誤后,控制台輸出如下:

 


  1. java.lang.OutOfMemoryError: Java heap space  
  2. Dumping heap to d:/a.dump …  
  3. Heap dump file created [23067302 bytes in 0.160 secs]  
  4. Exception in thread “main” java.lang.OutOfMemoryError: Java heap space  
  5. at geym.zbase.ch3.heap.DumpOOM.main(DumpOOM.java:19)  


可以看到,虛擬機將當前的堆導出,並保存到D:/a.dump文件下。使用MAT等工具打開該文件進行分析,如圖所示,可以很容易地找到這些byte數組和保存它們的Vector對象實例。有關MAT等工具的使用,可以參閱《實戰Java虛擬機-jvm故障診斷與性能優化》第7章。

 

jvm1

除了在發生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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM