java.lang.OutOfMemoryError: PermGen space

1.普通程序與java程序的運行對比

普通程序在運行時

  • 程序 —–編譯成—–>二進制碼/機器碼(機器碼與硬件底層相關)–>機器碼綁定底層 So:不同平臺下的程序只能在相應的操作系統、硬件(體系結構)上,就比如pc機的程序不能在mac上運行。

Java程序在運行時:

  • java程序 —–編譯成—–>java class(字節碼,與平臺無關,在任何的操作平臺上字節碼都是相同的 –>JVM(java虛擬機,負責將字節碼編譯成相應體系結構的代碼)–>在相應的平臺中運行。

2. OutOfMemoryError: PermGen space

  • 當永久保存區域的空間耗盡時OutOfMemoryError: PermGen 
    space就會發生,這個錯誤一般是由於內存泄漏導致的。所謂內存泄漏,是指java類和類加載器在被取消部署後不能被垃圾回收。怎麼會發生這種情況呢?舉個例子:假如我們有一個Student類,這個類是Web應用程序jar包的一部分,同時在Web服務器的lib文件夾中包含了某種日誌框架,其中有一個Log類提供register方法調用,從而使得別的類通過註冊就可以使用日誌功能。如果Student類被註冊了,那麼Log類就開始擁有了一個對Student對象的引用(reference)。當Student類取消部署時,它仍然是註冊Log類的,Log類仍然擁有對Student對象的引用,因此,Student對象永遠不會被垃圾回收。此外,由於Student對象擁有一個對它的ClassLoader的引用,所以ClassLoader本身永遠也不會被垃圾回收,從而導致由它加載的所有類都不會被回收。

  • 一個更爲典型的例子是使用代理對象。Spring和Hibernate常常爲某些類生成代理類,這些代理類也是通過類加載器加載的,並且存儲在永久保存區域的堆空間,它們永遠不會被丟棄,從而會導致永久保存區域的堆空間被填滿。

3.如何避免永久保存區域內存不足

  1. 增加PermGen堆的最大尺寸    當遇到java.lang.OutOfMemoryError:PermGen 
    space錯誤時,我們可以做的第一件事情是增加永久保存區域的最大尺寸,該尺寸的缺省設置是64 M,我們可以將它設置成128 
    M以上。這個工作不能通過常規的JVM參數 
    -Xms(設置初始堆大小)和-Xmx(設置最大堆大小)來完成,因爲前面已經提到,永久保存區域完全獨立於普通的Java堆,這些參數是用來設置普通的Java堆的。不過也有類似參數用於設置永久保存區域的規模:

    -Xms256M -Xmx512M -XX:PermSize=256m -XX:MaxPermSize=512m


  2. 避免使用靜態字段   確保在編寫Java類時,不要使用靜態變量作爲對其他對象的引用。

  3. 使用JDK動態代理,而不是CGLIB代理   一些第三方的框架,如CGLIB會吞食大量的PermGen。因此,當遇到PermGen錯誤時,應儘快升級cglib到最新版;改用JDK動態代理,也是一個不錯的選擇。

  4. 更新到最新版本Hibernate3.2   此外,新版本的Hibernate不再使用CGLIB作爲字節碼提供者了,所以及時升級Hibernate,會大大降低出錯的機會。

  5. 共用的jar文件放到共享目錄下   如果在服務器上同時發佈了多個應用,那麼應該把共用的jar文件放到所有應用都可以訪問的目錄下。針對Tomcat而言,如果Tomcat下面有多個應用,應儘可能地把lib目錄下共用的jar文件放到Tomcat的common\lib或shared\lib下,以避免重複發佈,發佈速度和運行速度上也會有所提升。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章