请选择 进入手机版 | 继续访问电脑版

设为首页 收藏本站
思科社区 关注
思科社区

  思科 CCO 登录 推荐
 找回密码
 立即注册

搜索
热搜: 邮件服务器
查看: 1365|回复: 1

【小目标,一个“译”】+ 如何在您的Java应用中查找并修复内存泄漏 (2)

[复制链接]
发表于 2018-10-1 10:19:50 | 显示全部楼层 |阅读模式
2)手动禁用和启用您代码的各个部分,并使用VisualVM之类的工具观察JVM的内存使用情况。


如果您步入了这一步,那就不得不卷起袖子,做一些体力劳动了。您需要通读您的所有代码,以试图找出发生泄漏的地方。作为帮助,我建议您使用VisualVM之类的工具。(当然,ThermostatMAT也是可行的。)


配置的VisualVM


1. 下载该工具。


2. 打开终端,到达目录.../visualvm_xyz/bin下,运行shell脚本'./visualvm' (或在Windows上运行visualvm.exe)。


3. 您会看到弹出的主窗口。如果展开“本地”并双击您正在运行的应用(如下图,我的应用是一个子Eclipse),您就可以看到它的各种属性。


4. Fedora上用VisualVM进行故障诊断:对我来说,最初我无法连接到自己的JVM,也不能使堆转储(heap-dumps)和分析(profiling)运行起来。于是我探索出了如下步骤


  • 确保用自己的登录用户身份运行它,而不是使用sudo
  • 对系统进行的全面更新(sudo yum update)
  • 考虑重新启动是否有所帮助。
  • 尝试在关闭所有正在运行的Java应用程序之后,再启动VisualVM


  • 5. 添加一些插件。在使用VisualVM之前,我事先添加了一些插件。请点击进入工具->插件->“可用插件”。请选择如下的插件(如果您喜欢,则可以随意浏览并添加更多的插件):

6.

  • 内存池
  • 可视的GC
  • 终止应用程序
  • VisualVM分析运行的代码


  • 现在运行您的Java应用程序。

  • VisualVM连接到您的应用程序。

  • 执行那些容易导致性能变缓的操作。

  • 检查“监控”和“内存池”选项卡。如果您看到在“监视器”选项卡中内存显示增加的话,那就按下“执行GC”(垃圾收集),并监视内存的使用情况是否有所减少。

  • 如果并不减少的话,那么就切换到“内存池”选项卡,并检查“Old Gen”。(最开始对象会停留在“Eden”中,然后通过Survivor空间进行过渡,比较旧的对象会被移到“Old Gen”池中。如果出现泄漏,则会出现在Old-Gen池里。)

  • 现在返回去,并注释掉程序代码的大部分,从而定位到应用程序开始变慢的位置。

  • 重复上述过程,直到应用程序完全不再有泄漏的发生。

  • 然后,经过反复迭代来重新启用代码的各个部分,并检查VisualVM的内存使用情况。一旦您的应用程序再次开始泄漏,则马上进入导致内存泄漏的该函数方法,从而进一步缩小代码的考察范围。

  • 最终,您将能够把问题缩小到具体某一个类,甚至某一个单一的方法上。请仔细验证所有文件的缓冲区是否已被关闭,而HashMap是否被正确的使用了。
  • 标准您的代码
    有时候会很难确定您那“金光闪闪”的新代码是否真的会比旧代码更好。面对这种情况下,您需要去标准化应用程序的性能。您可以将下面的这段代码插入到任何您认为适当的位置,以获取有关运行时间和垃圾收集次数的相关信息:


long start = System.currentTimeMillis();
..
//your code
..
long end = System.currentTimeMillis();
System.out.println("Run time:" + Long.toString(end - start));
System.out.println(printGCStats());
public static String printGCStats() {
longtotalGarbageCollections = 0;
longgarbageCollectionTime = 0;
for(GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
longcount = gc.getCollectionCount();
if(count >= 0) {
totalGarbageCollections += count;
}
longtime = gc.getCollectionTime();
if(time >= 0) {
garbageCollectionTime += time;
}
}
return "Garbage Collections:" + totalGarbageCollections + "n" +
"Garbage Collection Time (ms):" + garbageCollectionTime;
}


特别提醒一下:如果您是在主Eclipse中进行测试的话,我建议去测试一个“干净”的子Eclipse;或者是在您的Eclipse的一些“干净”实例中进行。因为这样的话,其他各种插件是不会对标准的耗时产生影响的。


附加说明:堆转储


我个人使用得并不多,但有些人比较热衷于“堆转储”。您可以在任何时候采取堆转储,然后查看有多少类的实例被打开,以及它们使用了多大的空间。您可以通过双击它们来查看具体的内容。如果您想获悉自己的应用程序产生了多少个对象的话,这种方法会非常有用。





我的应用并没有泄漏,可为何还是很慢


当然也存在着一种可能性:就算您的代码中并没有任何的泄漏,它仍然运行缓慢。如果出现这种情况的话,您就必须进行代码分析了。不过,代码分析已经超出了本文所涉及的范围。这里推荐一个很好的YouTube视频,它讲解了如何去使用免费和付费的分析器来对Eclipse进行分析,请参见:https://www.youtube.com/watch?v=YCC-CpTE2LU


还能哪些?


至此您可以潜下心来,花上一到两天的时间去修复您的内存泄漏问题了。在此过程中,如果您仍碰到麻烦的话,请参考如下的链接:


  • 捕捉内存泄漏:https://www.toptal.com/java/hunting-memory-leaks-in-java
  • 内部类的内存泄漏问题:https://blogs.oracle.com/olaf/entry/memory_leaks_made_easy
  • 浏览OracleJVM GC指南:www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
  • 【原标题】 How to Find and Fix Memory Leaks inYour Java Application
    作者: Leo Ufimtsev
    原文链接:https://dzone.com/articles/how-to-find-and-fix-memory-leaks-in-your-java-appl


  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
平均得分4 (2 评价)
发表于 2018-10-11 14:43:05 | 显示全部楼层
表示看不懂。。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
平均得分1 (1 评价)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver | 思科社区  

GMT+8, 2018-12-11 00:07 , Processed in 0.088613 second(s), 34 queries .

京ICP备09041801号-187

版权所有 :copyright:1992-2019 思科系统  重要声明 | 保密声明 | 隐私权政策 | 商标 |

快速回复 返回顶部 返回列表