如果应用程序长时间运行,则类丢失 [英] Classes missing if application runs for a long time

查看:59
本文介绍了如果应用程序长时间运行,则类丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有趣的问题-如果我的应用程序运行了很长时间(> 20小时),有时我会收到NoClassDefFound错误-似乎JVM决定该类无论如何都不会被使用,并对其进行GCd处理.

I have a funny problem - if my application runs for a long time (> 20h), then sometimes I get NoClassDefFound error - seems like JVM decided that the class is not going to be used anyway and GCd it.

更具体一点,下面是一个示例案例:

To be a bit more specific, here's an example case:

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块运行的时间较少,那么一切都会按预期进行.

If that try/catch block runs for smaller amounts of time, everything works as expected.

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

If anyone is interested, here is the codebase in question: Avalanche

我需要注意的是,仅在使用JRE 6u26和Scala 2.9.1/2.9.2的Cent OS 5机器上才看到此问题和类似问题.

I need to note that I saw this and similar problems only on Cent OS 5 machines, using JRE 6u26 and Scala 2.9.1 / 2.9.2.

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

What could be the cause of this problem?

推荐答案

如果尝试初始化一个类的内存不足,您是否会看到OutOfMemory或NoClassDef?

If you ran out of memory trying to initialize a class, do you suppose you'd see the OutOfMemory or the NoClassDef?

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

您的代码可能抛出了OOM,然后无法加载异常处理程序对象.

It's possible your code threw OOM, then couldn't load your exception handler object.

当然,还有其他可能的瞬态情况:网络中断,并且该类在网络驱动器上;或者您在测试过程中清理了类目录.另一种可能性是,您的应用程序是在不区分大小写的文件系统上构建的,并且正在使用名称异常的类文件在区分大小写的文件系统上进行测试.例如,如果在不删除* .class的情况下将对象"handler"更改为"Handler",则仍会看到"Handler.class". (但是我怀疑错误消息的详细信息会包含名称冲突;当然,除非您是OOM.)

There are, of course, other possible transient conditions: network was down and the class is on a networked drive; or you cleaned your classes directory during the test. Another possibility is that you built your app on a case-insensitive file system and are testing on a case-sensitive file system with an anomalously named class file. For example, if you change object "handler" to "Handler" without deleting *.class, you'll still see "Handler.class". (But I suspect the error message detail would include the name conflict; unless you're OOM, of course.)

我没有机会尝试破坏AbstractFileClassLoader;我以前的猜测是:

I haven't had a chance to try to break AbstractFileClassLoader; my previous speculation follows:

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

It's worth explaining that Avalanche is a build tool, and you run an instance of scalac to compile the build.scala to an in-memory classfile that is loaded with scalac's AbstractFileClassLoader, where "AbstractFile" is the abstraction. Since whatever build.scala mucks with the tool configuration, obviously it's essential that AFCL respect classloader delegation. That seems true, but I notice that it does not delegate first to parent on getResourceAsStream (as a quick test confirmed). The suspicious thing is that findClass uses classBytes, which on failure calls super, which is the nice ScalaClassLoader, but which uses getResourceAsStream to load Foo.class. So calling findClass could return a class from the parent CL (which is wrong), though that may be moot if the parent is known to have failed already. Because it's the middle of my night, I can't draw a conclusion, but I would want to nail that down if my build tool relied on this behavior.

我不知道运行一天的build.scala(或av.scala)中有什么,但是也许您是由行为不正常的子类加载器加载(重新)加载了Avalanche,然后当它抛出时, CL找不到您的ErrorHandler的类.

I don't know what's in your build.scala (or av.scala) that runs for a day, but perhaps you've got Avalanche (re-)loaded by a misbehaving child classloader, then when it throws, the CL can't findClass your ErrorHandler.

这篇关于如果应用程序长时间运行,则类丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆