如果应用程序长时间运行,则缺少类



我有一个有趣的问题-如果我的应用程序运行很长时间(>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$

如果try/catch块运行的时间较短,那么一切都会按预期进行。

如果有人感兴趣,这里是有问题的代码库:雪崩

我需要注意的是,我只在使用JRE 6u26和Scala 2.9.1/2.9.2的Cent OS 5机器上看到了这个和类似的问题。

这个问题的原因可能是什么?

如果您在尝试初始化类时内存不足,您认为会看到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,然后无法加载异常处理程序对象。

当然,还有其他可能的瞬态条件:网络中断,类在网络驱动器上;或者在测试期间清理了类目录。另一种可能性是,您在不区分大小写的文件系统上构建了应用程序,并在具有异常命名的类文件的区分大小写文件系统上进行测试。例如,如果您在不删除*.class的情况下将对象"handler"更改为"handler",您仍然会看到"handler.class"

我还没有机会尝试破坏AbstractFileClassLoader;我之前的推测如下:

值得解释的是,Avalanche是一个构建工具,您可以运行scalac的一个实例来将build.scala编译为内存中的类文件,该类文件由scalac的AbstractFileClassLoader加载,其中"AbstractFile"是抽象。由于任何build.scala都会干扰工具配置,因此AFCL尊重类加载器委托显然是至关重要的。这似乎是真的,但我注意到它并没有首先委托给getResourceAsStream上的父级(快速测试证实了这一点)。可疑的是,findClass使用classBytes,它在失败时调用super,这是一个很好的ScalaClassLoader,但它使用getResourceAsStream来加载Foo.class。因此,调用findClass可能会从父CL返回一个类(这是错误的),尽管如果已知父CL已经失败,这可能是没有意义的。因为现在是半夜,我无法得出结论,但如果我的构建工具依赖于这种行为,我想明确这一点。

我不知道你的build.scala(或av.scala)中运行了一天的是什么,但也许你的Avalanche(重新)被一个行为不端的子类加载器加载了,然后当它抛出时,CL无法找到Class你的ErrorHandler。

最新更新