显示带有标签的帖子漏洞.显示所有帖子
显示带有标签的帖子漏洞.显示所有帖子

2009年3月13日星期五

FOW:与内存泄漏作斗争

本周的今天专题更具技术性。您可能知道BibSonomy基于MySQL/Tomcat架构。通常BibSonomy运行非常稳定,但Java虚拟机有时会停止运行,并显示“java.lang.OutOfMemoryError:PermGen空间“错误。这主要发生在Tomcat上重新部署BibSonomy项目之后。为什么会发生这种情况?简单的答案是:因为Java虚拟机没有足够的内存用于所谓的永久发电空间。这个空间用于在主内存中保存Java类。一个简单的解决方案是为JVM提供更多的PermGen空间。但这并没有解决根本问题。通常JVM有足够的PermGen空间。提供更多内存的唯一结果是:错误将稍晚发生,而不是在重新部署后直接发生。

所以我们决定寻找内存泄漏的原因。很快我们发现,在web应用程序中有一些类是类加载器无法删除因为它们被“链接”到由标准类加载器加载的类。可能有几个原因为此和使用正确的工具(来自JDK的jmap和jhat)加上一些小程序来查找参考链,我们发现了罪魁祸首:

*MySQL连接器/J(请参见http://bugs.mysql.com/bug.php?id=36565)
*iBatis公司(请参见https://issues.apache.org/jira/browse/IBATIS-540)
*与杰波瑞菲
*Tomcat公司(请参见https://issues.apache.org/bugzilla/show_bug.cgi?id=46221)
*我们可以通过将一些JAR移动到正确的位置(另请参见在这里在这里).

识别受试者是一项反复的任务——修复一个泄漏导致的下一个泄漏。。。我们不知道一开始有这么多候选人。我们可以通过切换到新版本来修复iBatis,MySQL、JabRef和Tomcat的修复有点困难。
对于JabRef,我们必须修改源代码,使其不会启动AWT。此外,Tomcat生命周期监听器杀死了java.util.prefs。文件系统首选项webapp关闭后使用可怕的Java内省攻击:

final Class clazz=CleanupListener.Class.getClassLoader().loadClass(“java.util.prefs.FileSystemPreferences”);
final字段f=clazz.getDeclaredField(“syncTimer”);
f.setAccessible(真);
最终计时器计时器=(计时器)f.get(null);
timer.cancel();

为了修复MySQL错误,侦听器确保在启动web应用程序时,MySQL连接类在web应用程序之前加载,并由标准类加载器加载,这样取消计时器线程(这是泄漏的原因)不会阻止卸载web应用程序。Tomcat中StandardContext的记录器(无论出于何种原因,都是通过webapps类加载器加载的)也会被侦听器杀死。

经过几周的工作,我们得到了一个无泄漏的应用程序。糟糕的是,我们正在使用的每个库都可能导致泄漏,如果我们不小心,泄漏会很快恢复。不幸的是,我们没有意识到可以将一种方法放入Tomcat或应用程序中,该方法只检查内存泄漏。

希望你发现这个有趣,并祝你自己的应用程序好运。。。

热门帖子