tomcat 7中的内存泄漏org.apache.juli.ClassLoaderLogManager $ RootLogger

时间:2013-04-06 18:59:46

标签: java tomcat memory-leaks

我正在尝试在Web应用程序中诊断生产内存泄漏。该应用程序是在Tomcat 7和mySQL上运行的GWT应用程序,在Debian上运行OpenJDK 1.6.0_18。

我启动了tomcat并让应用程序泄漏了几天 - 没有重新加载应用程序 - 然后进行堆转储并在Eclipse MAT插件中打开它。我正试图理解我所看到的。看来tomcat登录类中有大量的内存(见下面的截图)。

我使用java日志框架在GWT servlet中进行基本日志记录。只是像

这样的基本调用
Logger.getAnonymousLogger().log(Level.INFO, "User" + userId + " did something interesting");
Logger.getAnonymousLogger().log(Level.SEVERE, exception.getMessage(), exception);

我在网上找到的唯一类似问题是blog post

任何人都可以解释这里可能发生的事情吗?为什么tomcat日志记录类会占用如此多的内存?

Screenshot of MAT analysis

为了使我更加困惑,它似乎抓住了大量的弱引用 - 但我似乎无法在MAT中弄清楚如何找出这些弱引用指向的内容,我也会期望在达到堆限制时收集弱引用,但tomcat会抛出内存异常。

Giant Array of Weak References

1 个答案:

答案 0 :(得分:3)

有趣的问题:)

看起来有数百万个类已经使用您的RootLogger注册了记录器。现在,除非您的项目中有数百万个类,否则:

  • 课程会定期拨打Logger.getAnonymousLogger()
  • 动态生成记录器或类:
    • 这些可能来自:
      • java.lang.reflect.Proxy
      • 一种脚本语言(如Groovy),您可以在其中动态创建类
      • 字节码操作库
      • 直接拨打new Logger(name)
    • 每个创建的类都会注册一个记录器 - LogManager.addLogger()
    • 一段时间后,Logger(以及任何创建的类)都是GCed

无论哪种方式,每个额外的记录器都会向包含弱引用的ArrayList添加另一行。弱引用通过指向记录器启动,但记录器正在进行GC,只留下空的弱引用。大量的弱引用导致OOM而不是它们(习惯)指向的对象。

修复?

  • 如果您使用匿名日志记录,请不要。这适用于Applets。
  • 看一下动态课程中是否有LogManager.addLogger。如果是,请强制记录器名称为常量
  • 检查您是否有new Logger(variable)之类的内容。如果这样做,那么您需要将变量更改为常量。