Rog*_*ach 6 jvm scala noclassdeffounderror classloader
我有一个有趣的问题 - 如果我的应用程序运行了很长时间(> 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)
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
Exception in thread "main" java.lang.NoClassDefFoundError: org/rogach/avalanche/ErrorHandler$
Run Code Online (Sandbox Code Playgroud)
如果try/catch块运行的时间较短,则一切都按预期工作.
如果有人有兴趣,这里是有问题的代码库:Avalanche
我需要注意的是,我只在Cent OS 5机器上看到了这个和类似的问题,使用的是JRE 6u26和Scala 2.9.1/2.9.2.
可能是造成这个问题的原因是什么?
如果您在尝试初始化类时内存不足,您认为您会看到 OutOfMemory 或 NoClassDef 吗?
//from initialize_impl
if (NULL == message) {
// Out of memory: can't create detailed error message
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
Run Code Online (Sandbox Code Playgroud)
您的代码可能抛出 OOM,然后无法加载异常处理程序对象。
当然,还有其他可能的瞬态情况:网络已关闭且类位于网络驱动器上;或者您在测试期间清理了您的类目录。另一种可能性是您在不区分大小写的文件系统上构建了应用程序,并使用异常命名的类文件在区分大小写的文件系统上进行测试。例如,如果将对象“handler”更改为“Handler”而不删除 *.class,您仍然会看到“Handler.class”。(但我怀疑错误消息详细信息将包括名称冲突;当然,除非您 OOM。)
我还没有机会尝试破坏 AbstractFileClassLoader;我之前的猜测如下:
值得解释的是,Avalanche 是一个构建工具,您运行 scalac 的实例来将 build.scala 编译为内存中的类文件,该类文件使用 scalac 的 AbstractFileClassLoader 加载,其中“AbstractFile”是抽象。由于无论 build.scala 对工具配置有何影响,显然 AFCL 尊重类加载器委托是至关重要的。这似乎是真的,但我注意到它不会首先委托给 getResourceAsStream 上的父级(正如快速测试所证实的那样)。可疑的是 findClass 使用 classBytes,它在失败时调用 super,这是很好的 ScalaClassLoader,但它使用 getResourceAsStream 来加载 Foo.class。因此,调用 findClass 可能会从父级 CL 返回一个类(这是错误的),尽管如果已知父级已经失败,那么这可能没有实际意义。因为现在是半夜,所以我无法得出结论,但如果我的构建工具依赖于这种行为,我想确定这一点。
我不知道运行一天的 build.scala (或 av.scala) 中有什么,但也许你已经通过行为不当的子类加载器(重新)加载了 Avalanche,然后当它抛出时,CL 可以' t findClass 你的ErrorHandler。
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |