天天看點

Java中OutOfMemoryError(記憶體溢出)的三種情況及解決辦法(轉)

相信有一定java開發經驗的人或多或少都會遇到outofmemoryerror的問題,這個問題曾困擾了我很長時間,随着解決各類問題經驗的積累以及對問題根源的探索,終于有了一個比較深入的認識。

在解決java記憶體溢出問題之前,需要對jvm(java虛拟機)的記憶體管理有一定的認識。jvm管理的記憶體大緻包括三種不同類型的記憶體區域:permanent

generation space(永久儲存區域)、heap space(堆區域)、java

stacks(java棧)。其中永久儲存區域主要存放class(類)和meta的資訊,class第一次被load的時候被放入permgen

space區域,class需要存儲的内容主要包括方法和靜态屬性。堆區域用來存放class的執行個體(即對象),對象需要存儲的内容主要是非靜态屬性。每

次用new建立一個對象執行個體後,對象執行個體存儲在堆區域中,這部分空間也被jvm的垃圾回收機制管理。而java棧跟大多數程式設計語言包括彙編語言的棧功能相

似,主要基本類型變量以及方法的輸入輸出參數。java程式的每個線程中都有一個獨立的堆棧。容易發生記憶體溢出問題的記憶體空間包括:permanent

generation space和heap space。

第一種outofmemoryerror: permgen

space

發生這種問題的原意是程式中使用了大量的jar或class,使java虛拟機裝載類的空間不夠,與permanent

generation space有關。解決這類問題有以下兩種辦法:

1.

增加java虛拟機中的xx:permsize和xx:maxpermsize參數的大小,其中xx:permsize是初始永久儲存區域大小,xx:maxpermsize是最大永久儲存區域大小。如針對tomcat6.0,在catalina.sh

或catalina.bat檔案中一系列環境變量名說明結束處(大約在70行左右) 增加一行:

java_opts=" -xx:permsize=64m -xx:maxpermsize=128m"

如果是windows伺服器還可以在系統環境變量中設定。感覺用tomcat釋出sprint+struts+hibernate架構的程式時很容易發生這種記憶體溢出錯誤。使用上述方法,我成功解決了部署ssh項目的tomcat伺服器經常當機的問題。

2.

清理應用程式中web-inf/lib下的jar,如果tomcat部署了多個應用,很多應用都使用了相同的jar,可以将共同的jar移到tomcat

共同的lib下,減少類的重複加載。這種方法是網上部分人推薦的,我沒試過,但感覺減少不了太大的空間,最靠譜的還是第一種方法。

第二種outofmemoryerror: 

java heap space

發生這種問題的原因是java虛拟機建立的對象太多,在進行垃圾回收之間,虛拟機配置設定的到堆記憶體空間已經用滿了,與heap

space有關。解決這類問題有兩種思路:

1. 檢查程式,看是否有死循環或不必要地重複建立大量對象。找到原因後,修改程式和算法。

我以前寫一個使用k-means文本聚類算法對幾萬條文本記錄(每條記錄的特征向量大約10來個)進行文本聚類時,由于程式細節上有問題,就導緻了java

heap space的記憶體溢出問題,後來通過修改程式得到了解決。

2. 增加java虛拟機中xms(初始堆大小)和xmx(最大堆大小)參數的大小。如:set java_opts= -xms256m

-xmx1024m

第三種outofmemoryerror:unable to create new native

thread