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

Scala 如果应用程序长时间运行,则缺少类,scala,jvm,classloader,noclassdeffounderror,Scala,Jvm,Classloader,Noclassdeffounderror,我有一个有趣的问题——如果我的应用程序运行了很长一段时间(>20h),那么有时会出现NoClassDefFound错误——看起来JVM决定无论如何都不使用该类,并将其GCd 更具体地说,下面是一个示例: object ErrorHandler extends PartialFunction[Throwable,Unit] { def isDefinedAt(t: Throwable) = true def apply(e: Throwable) =e match { // ...

我有一个有趣的问题——如果我的应用程序运行了很长一段时间(>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”。(但我怀疑错误消息的详细信息会包括名称冲突;当然,除非您是OOM。)

我还没有机会尝试破解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)中有什么内容,但可能是一个行为不端的子类加载器重新加载了雪崩,然后当它抛出时,CL找不到对错误处理程序进行分类。

尝试使用
-XX:-TraceClassUnloading
运行它。结果如何@ron-我现在正在尝试,但这需要一些时间:)并且日志文件非常长且冗长,我应该为哪些单词对其进行grep以获得跟踪输出?蒙住眼睛猜不到,但“可疑”下的类名确实是一个候选项:)仍然没有抓住它:(这似乎是一个暂时的错误。好吧,你可能是对的,但我在另外两种情况下观察到了类似的行为,在这两种情况下,我没有弄乱类加载器。而将所有这些情况结合在一起的主题似乎是部分函数。我对类加载器几乎一无所知,但使用的是
AbstractFileClassLoader
)只加载那个
Build
类,所有其他类都应该通过默认的类加载器。或者是否存在某种机制,通过这种机制,子类加载器可以开始替代其父类?