2010-01-12 85 views
17

我讀了幾篇文章,我明白以下內容(請指正和/或編輯的問題,如果我錯了):爲什麼PermGen空間不斷增長?

Java堆分割這樣的:

  • 年輕一代:創建的對象去這裏,這部分是經常和廉價地收集垃圾

  • 老一代:在年輕一代的垃圾收集生存的對象去這裏,這個地區是垃圾收集較少,並使用更多的CPU要求過程/算法(我相信這就是所謂的標記 - 清除)

編輯:由另一個用戶說,PermGen的不是區域稱爲heap

  • PermGen的一部分:這個地區充滿你的應用程序類的元數據和許多其他的東西不依賴於應用程序的使用。

因此,知道這......爲什麼我的PermGen空間在應用程序處於重負載時增長?對於我之前所說的空間,儘管應用程序負載不應該增量填充,但正如我在開始時所說的,可能我對某些假設是錯誤的。

事實上,如果PermGen的空間越來越大,有沒有垃圾的方式收集或重置?

+0

請問您是否可以進一步澄清您的燙髮電池正在增長時發生了什麼?你如何看待你的燙髮器正在增長? – 2010-01-12 19:54:32

回答

19

事實上,在Sun的JVM永久代(PermGen的)是從堆完全分開。你確定你沒有看着Tenured Generation嗎?如果你的永久代繼續增長,這將是可疑的。

如果您的燙髮產品不斷增長,這是一個難以深入的領域。一般來說,它應該在第一次加載新類時增長(並且反射的某些用途也可能導致這種情況)。 Interned字符串也存儲在perm gen中。

如果您碰巧在Solaris上,可以使用jmap -permstat轉儲出perm gen統計信息,但該選項似乎不適用於Windows(以及其他平臺)。這裏是the documentation on jmap for Java 6

從Sun的guide on JConsole(這將讓你查看這些池的大小):

有關,以HotSpot Java虛擬機,存儲 池串行垃圾收集 有以下幾種。

  • 伊甸園空間(堆):大多數對象最初爲其分配內存的池 。
  • 生存空間(堆):包含生存 伊甸園 空間的垃圾收集對象池。
  • 時間生成(堆):包含對象的池在存活空間中存在 一段時間。
  • 永久生成(非堆):包含虛擬機本身的所有反射 數據的池,例如類和方法對象的 。通過 使用類數據共享的Java虛擬機, 這一代被劃分爲 只讀和讀寫區域。代碼緩存(非堆):HotSpot Java VM還包含一個代碼緩存, 包含的內存用於 編譯和存儲本機 代碼。
2

你對類加載器鏈做了些什麼樣的事情嗎?你在一串字符串上打電話intern()

+0

不,應用程序的「沉重部分」在於反序列化大對象圖,但該圖主要是內部帶有字符串的HashMaps。也許這叫'實習生'? – 2010-01-12 19:35:05

+2

沒有。HashMap不會調用intern()。 – 2010-01-12 19:37:55

6

我見過的最常見的原因是:

  • 自定義類加載器在加載換新後不仔細騰出舊的課程。
  • 多次重新部署應用程序後在PermGen中保留的類(在Dev中比Dev更常見)
  • 大量使用代理類,它們是在運行時合成創建的。當一個類定義可以重複用於多個實例時,創建新的代理類很容易。
6

這是一個比較煩人的調試問題。有很多原因可以讓你看到越來越多的permgen使用。這裏有兩個鏈接,我發現它們在理解漏洞如何發生以及跟蹤導致它們的原因時非常有用。

http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html

http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html

+0

+1的真棒鏈接。上週我偶然發現了其中一個,但之後失去了聯繫。 – 2010-01-12 20:29:11

0

我見過的最常見的原因是:

  1. Java類加載
  2. JAXBContext.newInstance
  3. String.intern()