你是否有一个Java应用程序,它一开始运行良好,但过了一段时间就变慢了,还是它对少量文件运行良好,但对于大量文件,性能会下降?也许你的内存泄露了。
当修复内存泄漏时;如果有人问我:“如果你当时知道你现在知道的,你会告诉自己什么?”
嗯,我想说。。。(你不讲武德。。。)
一开始工作很快,但随着时间的推移会变慢。
如果您忘记关闭资源,或者对对象的引用未释放,则可能会发生这种情况。例如:
equals()
和hashcode()
,则哈希映射保持引用的活动性,如下代码
有两种方法。第一种是“快速修复”尝试。如果失败了,那你就得走漫长的路了。
对于符合jdk1.5+的代码,eclipse将针对明显的泄漏情况向您发出警告和错误。更准确地说,任何实现closable(从1.5开始)(例如outputstream从1.5开始)的引用被破坏但对象没有关闭时,都会向您抛出警告。然而,在eclipse项目中并不总是启用泄漏检测。你可能得先打开它们。转到项目设置并启用它们,如下所示:
现在eclipse将概述内存泄漏:
然而,即使使用花哨的Eclipse hocus pocus,也不能检测到所有的文件关闭和泄漏。尤其是在处理遗留代码(1.5之前的版本)时,很可能会遇到泄漏,因为它们是在实现“closable”之前编写的。或者有时文件打开/关闭嵌套得太深,以至于eclipse无法检测到它们。如果你在这个地方,你可以试试第二步。
如果你走到这一步,你就得卷起腰来做些体力活。您可以阅读所有代码并尝试了解泄漏发生在哪里。为了帮助您完成这个过程:我建议您尝试使用这样的工具。(MAT也能可以)
3. 你应该看到主窗口。如果您展开'local'并双击正在运行的应用程序(在我的例子中是一个子eclipse),您可以看到配置属性:
4. 使用VisualVM进行故障排除(如果它工作正常,就跳过这个:对我来说,最初我无法连接到我的JVM,我无法进行堆转储,并且分析也不起作用。以下是一些可能有帮助的步骤:
5. 添加一些插件。在VisualVM对我有用之前,我首先要添加一些插件。转到“工具”->“插件”->“可用插件”。选择以下插件(请随意浏览并添加更多插件):
1. 现在运行Java应用程序,
3. 执行导致性能下降的操作。
4. 检查“监视器”和“内存池”选项卡。如果在“Monitor”选项卡中看到内存增加,请尝试按“performgc”(垃圾收集),看看这是否会减少内存使用。
5. 然后切换到“内存池”选项卡并检查“老年代”。(对象首先在“伊甸园eden”中徘徊,然后通过幸存者空间过渡,较老的物体进入“老一代”。如果有东西漏了,就在老年代里)
6. 现在返回并注释掉程序的大部分代码,直到应用程序刚刚启动和停止为止。
7. 重复上述步骤,直到应用程序完全不泄漏为止。
8. 然后通过多次迭代重新启用部分代码并检查VisualVM内存使用情况。当应用程序再次开始泄漏时,进入导致内存泄漏的方法并进一步缩小范围。
9. 最终,您将把问题缩小到单个类,甚至可能是单个方法。一旦你到了那里,仔细验证所有文件缓冲区是否关闭,哈希映射是否正确使用。
有时很难判断你的新代码是否比旧代码更好。在这种情况下,您可能需要对应用程序的性能进行基准测试。以下是一些代码,您可以插入到正确的位置,以获取有关运行时和垃圾回收运行次数的信息:
在任何时候,您都可以获取堆转储,然后查看有多少类实例处于打开状态,以及它们使用了多少空间。你可以双击它们来查看它们的内容。如果您想查看应用程序生成了多少对象,这很有用。
你还可以参考这篇文章: