處理“java.lang.OutOfMemoryError: PermGen space”錯誤
一、概述
PermGen(永久代)是為運行基於 JVM 的應用程序分配的一塊特殊內存。 PermGen 錯誤是java.lang.OutOfMemoryError
系列中的一個,它表示資源(內存)耗盡。
在這個快速教程中,我們將了解導致java.lang.OutOfMemoryError
: Permgen space 錯誤的原因以及如何解決它。
2. Java 內存類型
JVM 使用兩種類型的內存:堆棧和堆。堆棧僅用於存儲原始類型和對像地址。相反,堆包含對象的值。當我們談論內存錯誤時,我們總是指的是堆。實際上,PermGen 是堆內存的一部分,但與 JVM 的主內存分離和處理方式不同。要掌握的最重要的概念是,可能有大量可用空間保留在堆中,並且仍然耗盡 perm gen 內存。
PermGen 的主要範圍是存儲 Java 應用程序運行時的靜態內容:特別是,它包含靜態方法、靜態變量、對靜態對象的引用和類文件。
3. java.lang.OutOfMemoryError
: PermGen
簡單地說,當為 PermGen 分配的空間不再能夠存儲對象時,就會發生此錯誤。發生這種情況是因為 PermGen 不是動態分配的,並且具有固定的最大容量。 64 位版本的 JVM 的默認大小為 82 Mb,舊的 32 位 JVM 的默認大小為 64 Mb。
PemGen 耗盡的最常見原因之一是與類加載器相關的內存洩漏。實際上,PermGen 包含類文件,類加載器負責加載 Java 類。類加載器問題在應用服務器中很常見,其中實例化了多個類加載器以實現各種應用程序的獨立部署。
當應用程序被取消部署並且服務器容器保留一個或多個類的引用時會出現問題。如果發生這種情況,類加載器本身就不能被垃圾回收,從而使 PermGen 內存與他的類文件飽和。 PermGen 崩潰的另一個常見原因是應用程序線程在應用程序取消部署後繼續運行,從而維護分配在內存中的多個對象。
4. 處理錯誤
4.1。調整正確的 JVM 參數
對於有限的內存空間,首先要做的是盡可能增加該空間。通過使用特定的標誌,可以增加 PermGen 空間的默認大小。具有數千個類或大量 Java 字符串的大型應用程序通常需要更大的 PermGen 空間。通過使用JVM 參數– XX:MaxPermSize
可以指定更大的空間來分配給這個內存區域。
由於我們提到了 JVM 標誌,因此還值得一提的是一個不常用的標誌,它會觸發此錯誤。 Xnoclassgc
JVM 參數,當在 JVM 啟動時指定時,會從要丟棄的實體列表中顯式刪除類文件。在應用程序服務器中以及在每個應用程序生命週期中加載和卸載類數千次的現代框架中,這可能會很快耗盡 PermGen 空間。
在舊版本的 Java 中,類是堆的永久部分,這意味著一旦加載,它們就會保留在內存中。通過指定CMSClassUnloadingEnabled
(對於 Java 1.5 或CMSPermGenSweepingEnabled
對於 Java 1.6) JVM 參數,可以啟用類的垃圾收集。如果我們碰巧使用的是 Java 1.6, UseConcMarkSweepGC
也必須設置為true.
否則, CMSClassUnloadingEnabled
參數將被忽略。
4.2.升級到 JVM 8+
修復此類錯誤的另一種方法是升級到更新版本的 Java。從 Java 版本 8 開始, Permgen 已完全被 Metaspace 取代,Metaspace具有自動調整大小的空間和可以清理死類的高級功能。
4.3.堆分析
值得注意的是,如果發生內存洩漏,所提供的任何解決方案都不能滿足要求。內存將完成,無論大小。即使元空間也有有限的可用內存量。深度 HEAP 分析有時是唯一的解決方案,可以使用 VisualGC 或 JPROFILER 等工具進行。
五、總結
在這篇簡短的文章中,我們看到了 PermGen 內存的用途以及與堆內存的主要區別。接下來,我們了解了java.lang.OutOfMemoryError
: Permgen 錯誤的含義以及在哪些特殊情況下會被觸發。在上一節中,我們重點介紹了在嘗試解決這個特殊問題時可以使用的各種解決方案。