2012-09-13 33 views
6

我有一個有趣的問題 - 如果我的應用程序運行了很長時間(> 20h),那麼有時會得到NoClassDefFound錯誤 - 看起來像JVM認爲該類不會成爲無論如何,GCd它。如果應用程序運行很長時間,則缺少類

要成爲一個更具體一點,下面是一個例子情況:

object ErrorHandler extends PartialFunction[Throwable,Unit] { 
    def isDefinedAt(t: Throwable) = true 
    def apply(e: Throwable) =e match { 
    // ... handle errors 
    } 
} 

// somewhere else in the code... 
try { 
    // ... long running code, can take more than 20 hours to complete 
} catch (ErrorHandler) 

而且我得到以下異常:

Exception in thread "main" java.lang.NoClassDefFoundError: org/rogach/avalanche/ErrorHandler$ 

如果嘗試少量的時間/ catch塊運行,一切按預期工作。

如果有人有興趣,這裏是有問題的代碼庫:Avalanche

我需要注意的是我看到了這一點,類似的問題只能在Cent OS 5機,使用JRE 6u26和Scala 2.9.1/2.9.2。

這個問題的原因是什麼?

+4

嘗試用'-XX:-TraceClassUnloading'運行它。結果是什麼? http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html – ron

+0

@龍 - 我現在正在嘗試,但它會需要一些時間:)和日誌文件是相當長的和冗長,爲什麼我應該grep它來獲得跟蹤輸出? – Rogach

+0

不能猜到被蒙上眼睛,但嫌疑人的類名肯定是候選人:) – ron

回答

1

如果您嘗試初始化某個類的內存不足,您是否會看到OutOfMemory或NoClassDef?

//from initialize_impl 
    if (NULL == message) { 
    // Out of memory: can't create detailed error message 
    THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className); 

它可能是你的代碼扔OOM,然後無法加載你的異常處理程序對象。

當然,還有其他可能的瞬態情況:網絡故障,班級在網絡驅動器上;或者在測試過程中清理了你的classes目錄。另一種可能性是,您在不區分大小寫的文件系統上構建應用程序,並且正在使用異常命名的類文件在區分大小寫的文件系統上進行測試。例如,如果您在不刪除* .class的情況下將對象「處理程序」更改爲「處理程序」,您仍然會看到「Handler.class」。 (但我懷疑錯誤消息的詳細信息會包含名稱衝突;除非你是OOM,當然。)

我沒有機會嘗試打破AbstractFileClassLoader;我之前的猜測如下:

值得說明的是,Avalanche是一個構建工具,並且您運行一個scalac實例將build.scala編譯爲內存類文件,該文件使用scalac的AbstractFileClassLoader加載,其中「AbstractFile」爲抽象。由於無論build.scala如何使用工具配置,AFCL都必須尊重classloader委託。這似乎是真的,但我注意到,它不會首先委託給getResourceAsStream上的父(作爲快速測試確認)。可疑的是,findClass使用classBytes,失敗時調用super,這是很好的ScalaClassLoader,但它使用getResourceAsStream來加載Foo.class。所以調用findClass可以從父CL返回一個類(這是錯誤的),儘管如果已知父類已經失敗,那可能是沒有意義的。因爲這是我的夜晚的中間,所以我不能得出結論,但是如果我的構建工具依賴於此行爲,我會想要指出這一點。

我不知道你的build.scala(或av.scala)運行了一天的內容,但也許你有Avalanche(重新)由行爲不當的子類加載器加載,然後當它拋出時, CL無法找到你的ErrorHandler類。

+0

嗯,你可能是對的,但我在另外兩種情況下觀察到了類似的行爲,我沒有混淆類加載器,並且統一所有這些情況的主題似乎是部分函數。 – Rogach

+0

我對類加載器幾乎一無所知,但使用了'AbstractFileClassLoader'(我認爲)只是爲了加載這個'Build'類,所有其他的類都應該通過默認的類加載器。還是有一些機制,子類加載器可以通過它來替代它的父類? – Rogach

相關問題