2009-09-20 70 views
41

我正在開發標準電梯平臺(maven和碼頭)。我反覆得到這個(每對夫婦一次天):PermGen與電梯和碼頭問題

Exception in thread "[email protected]" java.lang.OutOfMemoryError: PermGen space 
2009-09-15 19:41:38.629::WARN: handle failed 
java.lang.OutOfMemoryError: PermGen space 

這是在我的開發環境。這不是問題,因爲我可以繼續重新啓動服務器。在部署中,我沒有這些問題,所以它不是一個真正的問題。我只是好奇。

我不太瞭解JVM。我認爲我認爲永久世代記憶是用於類和字符串之類的東西是正確的嗎?我記得有點與.NET內存模型混在一起...

任何這種情況發生的原因?默認值是瘋狂的低?它與Scala必須爲函數對象和類似的FP事物創建的所有輔助對象有關嗎?每次我用新編寫的代碼重新啓動Jetty(每隔幾分鐘),我想它會重新加載類等等。但即便如此,它不可能是那麼多嗎? JVM不應該能夠處理大量的類嗎?

乾杯

+1

正如https://web.archive.org/web/20150105090518/http://www.scala-blogs.org/2007/12/scala-statically-typed-dynamic-language提及。 HTML文章:「JVM的代垃圾收集器對這樣的情況進行了優化,因爲隱式創建的對象是短命的,他們會GC非常漂亮。」但如果這些對象不是短命的,那是另一回事。 – VonC 2009-09-20 18:49:08

回答

44

this post

這異常發生,原因很簡單:
permgenspace就是類的屬性,如方法,字段,註釋,也靜態變量等存儲在Java VM,但是這個空間具有不被垃圾收集器清理的特殊性。 所以如果你的web應用程序使用或創建了很多類(我正在考慮幾代動態類),那麼你很可能遇到了這個問題。 這裏有一些解決方案,幫助我擺脫這個異常:

  • -XX:+CMSClassUnloadingEnabled:該設置可以對垃圾收集在permgenspace
  • -XX:+CMSPermGenSweepingEnabled:允許垃圾收集器從內存中刪除,甚至類
  • -XX:PermSize=64M -XX:MaxPermSize=128M:增加了分配給超大空間的內存量

可能會有所幫助。

編輯2012(近3年後)七月:

Ondra Žižka評論(我已經更新上面的答案):

JVM 1.6.0_27說:請使用:

  • CMSClassUnloadingEnabled(使用CMS GC時是否啓用類卸載功能)
  • 代替CMSPermGenSweepingEnabled未來

查看完整的Hotspot JVM Options - The complete reference爲mroe。

+1

謝謝。我認爲調整GC的行爲或PermGen的大小可以解決問題。我真的在尋找一個具體的原因,爲什麼(/ if)Lift會膨脹PermGen對象。 – Joe 2009-09-20 18:37:06

+1

可能是由於由Lift執行的一些動態類生成。 – VonC 2009-09-20 18:47:34

+3

JVM 1.6.0_27說:將來請使用'CMSClassUnloadingEnabled'來代替'CMSPermGenSweepingEnabled'。 – 2012-07-23 01:47:16

1

持久代是在JVM把收集的,如自定義類加載器的東西,可能不會(垃圾)。

根據您部署的內容,燙髮設置可能較低。某些應用程序和/或容器組合確實包含一些內存泄漏,所以當某個應用程序取消部署時,有時候會收集類加載器等某些內容,導致填充Perm空間,從而產生您正在使用的錯誤。

不幸的是,目前在這種情況下,最好的選擇是最大了以下JVM標誌燙髮空間(例如用於192米燙髮大小):

-XX:MaxPermSize=192M (or 256M) 

另一種選擇是,以確保無論是容器或框架不會泄漏內存。

+0

MaxPermSize和192m之間需要有'='。 – 2010-12-06 17:04:33

2

郵件列表(http://groups.google.com/group/liftweb/)是電梯的官方支持論壇,在這裏你就可以得到更好的答案。我不知道你的開發設置的細節(你不進入太多細節),但我相信你在重裝碼頭你的戰爭,而無需實際重新啓動它。 Lift不會執行動態類生成(如上面的VonC所建議的那樣),但是Scala會將每個閉包編譯爲一個單獨的類。如果您要添加和在數天的過程中刪除關閉你的代碼,它可能是過多的類裝載和卸載從未和佔用空間燙髮。我建議你啓用上述VonC提到的選項JVM選項,看看它們是否有幫助。

+1

謝謝。我通常會發布到Google小組,但我想我會給StackOverflow一個去。將嘗試增加數字。 – Joe 2009-09-20 19:11:51

3

這是因爲類的重載的如你所說。如果你正在使用大量的庫,那麼類的總數將在每次重啓時迅速增長。嘗試使用VisualVM監控您的jetty實例,以獲得重新加載時內存消耗的概述。

12

如果您在運行時看到此信息mvn jetty:run, 請設置MAVEN_OPTS

對於Linux:

export MAVEN_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M" 
mvn jetty:run 

對於Windows:

set "MAVEN_OPTS=-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M" 
mvn jetty:run 

現在應該罰款。如果不是,則增加-XX:MaxPermSize

你也可以把這些永久您的環境。