2011-06-14 49 views
15

我看到'java.lang.OutOfMemoryError:PermGen space',同時運行〜300 JUnit測試和使用Spring上下文。有一個艱難的時間搞清楚什麼是吃了PermGen的,因爲:除了Class對象之外,還存儲在Perm Gen Space(sun 1.6 VM)中?

穩態
  • 應用程序消耗的PermGen space的
  • 我已經試過-XX約90米:MaxPermSize參數=256米單元測試 - 仍在運行的
  • 使用-XX:+TraceClassLoading-XX:+TraceClassUnloading啓用時,在執行OutOfMemoryError之前的最後20-30次測試時,沒有看到額外的「加載」事件。

後者似乎表明,除了Class對象之外的東西正在填充PermGen,不是嗎?如果是這樣,它會是什麼?例如,實例是否存儲在PermGen中?

這裏是我的VM信息:

$ java -version 
java version "1.6.0_25" 
Java(TM) SE Runtime Environment (build 1.6.0_25-b06) 
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode) 

相關

FWIW,即沉澱這個帖子我的問題的根源竟然是有點微不足道:我認爲Maven的Surefire插件繼承VM設置從MAVEN_OPTS(或運行mvn的VM實例)中,當它分出一個VM時 - 它不是(boo)。必須在插件的配置中明確指定使用argLine的那些。 HTH。

+1

的JProfiler或YourKit會給你裏面有什麼了更多的信息。 – bmargulies 2011-06-14 17:40:31

+0

@bmergulies - 使用探查器的好主意! – 2011-06-14 17:44:49

+0

沒有看到你的代碼,我的第一個想法是,每個測試用例都在實例化spring上下文。 – Woot4Moo 2011-06-14 17:46:05

回答

4

有時濫用String.intern()會導致PermGen空間錯誤,因爲interned字符串實例存儲在PermGen中。

這可能是你所看到的 - 試着消除不必要的String.intern()調用來查看是否解決了這個問題。在一般情況下,我不建議使用中的String.intern(),除非你確信以下兩個條件都爲真:

  • 你一定要添加字符串只有數量有限的
  • 實際上
  • 你需要這樣的字符串共享相同的對象標識(例如,如果相同的字符串很多情況下會消耗不可接受量的內存,或者您需要依靠==針對複雜性能的原因字符串比較)
+0

正確的,忘了String.intern() - 接受答案(不幸的是,在我的情況下,這不是OutOfMemoryError的原因) – Nikita 2011-06-14 21:04:14

+0

@Gweebz我接受了最直接解決我發佈的顯式問題的答案。如果這是錯誤的,我不希望是正確的; - – Nikita 2011-06-15 21:47:37

2

實習字符串也存儲在permgen中,儘管數百兆字節的字符串不太可能。記住你正在使用代理的每個Spring Bean都會在運行時即時生成新的類來實現你正在代理的接口。 (或者你的類,如果你使用CGLIB代理等)所以如果你爲每個JUnit創建一個'全新的'Spring ApplicationContext,那麼你實際上可以得到300個你所有代理的拷貝等。

記得Class的實例在每個類加載器中是唯一的,而不是跨整個permgen空間,所以實際上可能會有重複,這取決於你的運行方式是如何設置的(如果它涉及在容器中部署或者其他東西,儘管這在JUnit中似乎也不太可能:))。

+0

好的一點,但我沒有創建一個新的Spring ctx每個測試 - 一個ctx最初創建,在所有測試中共享,並在300次測試運行期間刷新一次。 實時生成新類:但是,如果在生成時不生成[Loading xxx]日誌條目(由於-XX:+ TraceClassLoading),該類會生成嗎?我一段時間都看不到那些 – Nikita 2011-06-14 21:07:33

1

我注意到你正在運行一個64位的JVM。這些已知可以在您的機器上使用兩倍的實際內存,因爲每個分配需要兩倍的內存空間。

如果你有JUnit測試實際加載了一個spring上下文(畢竟不是Unit),它們將實例化appContext中的所有bean。這很可能需要超過128MB(64位盒子上的256mb)內存。根據我的經驗,在64位機器上爲大型測試套件分配一半或更多的演出並不荒謬。嘗試將其提高到512MB甚至1GB。

這是我跑我的大項目的測試套件的一個選項與...

-Xms256m 
-Xmx512m 
-XX:MaxPermSize=512m 
+0

如果你不需要一個非常大的堆,你可以通過CompressedOops來緩解這個問題:http://wikis.sun.com/display/HotSpotInternals/CompressedOops – gpeche 2011-06-14 18:42:13

相關問題