ClassLoader泄漏 – 他们值得解决吗?

ClassLoader泄漏通常会导致java.lang.OutOfMemoryError:PermGen 。 在处理应用程序服务器的过程中,您可能会看到这是许多重新部署常见应用程序的结果。 可以在这两个链接上看到对此问题的解释和可能的解决方案。 (其中包括)

http://dev.eclipse.org/blogs/memoryanalyzer/2008/05/17/the-unknown-generation-perm/ http://blogs.oracle.com/fkieviet/entry/classloader_leaks_the_dreaded_java

现在大部分时间他们很容易绕过。 只需增加-XX:MaxPermSize,当不可避免的情况发生时,完全重启JVM。 尝试解决这个问题的问题是,在大型应用程序中,许多类可能导致类加载器泄漏,因此类仍然保留在permgen中。

由此产生两个问题:

是否合理地说这样的问题更好地增加最大烫发大小并在必要时重新启动或者应该找到更高优先级的解决方案?

有没有更简单的方法来解决类加载器泄漏?

它实际上取决于应用程序,或者更确切地说,取决于所使用的部署过程。 许多应用程序只在开发期间进行了重新调整,新版本每隔几个月发生一次,并且应用程序服务器因其他原因重新启动,远远超过部署应用程序。 在这种情况下,追逐Classloader泄漏是浪费时间。

当然,如果您计划实施持续部署过程 ,尤其是在高可用性环境中,那么Classloader泄漏是您真正需要解决的问题。 但是,在成为问题之前,还有许多其他事情需要比大多数项目做得更好。

@biziclop是对的。 你需要务实这一点。

如果问题仅出现在测试服务器中,您可能会认为这不值得努力解决。

如果问题出在生产服务器上,那么您需要一个解决方案或解决方法。 解决方案很难,但解决方法可能不那么有效:

  • 解决方法#1 – 不要对生产服务器进行热部署; 只进行完全重新部署和重启。

  • 解决方法#2 – 定期完全重启生产服务器,以避免耗尽permgen空间。 将此与增加permgen空间相结合。

在资源充足/运行良好的环境中,您应该在不同的服务器上进行所有测试。 如果需要考虑完整部署的停机时间,则应使用服务器复制和渐进式重新部署来最大限度地减少重新部署中断。 不需要热部署到生产。

如果您处于没有测试环境的位置,并且经常对生产机器进行热部署以最大限度地减少停机时间,那么您正在滑冰。 很有可能你最终会犯一个错误导致损失需要很长时间才能恢复……

是的,有更简单 – 更合适 – 解决泄漏的方法。 将ClassLoader Leak Prevention库添加到您的项目中,它应该为您解决问题!

如果您想自己追踪泄漏, 这个博客系列将会有所帮助。

我会务实地解决问题:

  1. 它是否在生产环境中引起问题?
  2. 你有足够的时间和资源来追踪它吗?

如果这两个问题的答案都是肯定的,那么一定要去做。 如果是一个是,一个不,那可能由管理层来决定,如果两者都不是,就不要打扰。

那些是最严重的泄漏之一……但任何泄漏都是邪恶的。 所以,我个人解决了这些问题。 分析也有帮助。 本身没有简单的方法,但是:

  • 线程进入每个模块的threadGroups + starter线程,以确保新的Threads()具有该组。
  • 特别注意Thread.inheritedAccessControlContext(它包含对类加载器的引用)
  • WeakReferences当你需要保留类时,实际上为听众使用WeakReferences,所以没有人可以跳过de-registers(并且只使用annon.clasess)。 拥有WeakListeners的框架确实有帮助。
  • 额外关心数据库驱动器,java.security.Provider
  • 更多技巧(包括类文件的动态增强,但通常是过度杀伤)

底线:


泄漏是邪恶的。