background image

  

  ▲程序执行 1 小时后 jmap 的输出结果,显示超过 2 千 5 百万个 CelleData 类实例

  现在有超过 2 千 5 百万个 CelleData 类实例,占用了超过 1GB 内存!我们可以确认这是
一个内存泄露。
  这类数据信息的好处是,不仅非常有用而且对于很大的 JVM 堆也能快速反馈结果。
我曾经试过检测一个运行频繁并且占用 17GB 堆内存的程序,使用 jmap 能够在 1 分钟内
生成程序的性能统计图。

 

   需要注意的是,jmap 不是运行分析工具,在生成统计图时 JVM 可能会暂停,因此

 

当生成统计图时需要确认这种暂停对程序是可接受的。以我的经验,通常在 调试一个严
重 bug 时需要生成这种统计图,这种情况下,这些 1 分钟的暂停对程序来说是可接受的。

 

这里,我们引出了下一个话题 - 半自动的运行分析工具 VisualVM。
  VisualVM
  另一个包含于 JVM

 

中的工具是 VisualVM

,它的开发者将它描述为 一种集成了多个

JDK

 

命令行工具的可视化工具,它能为您提供轻量级的运行分析能力 。这样看 来 ,

VisualVM 是另一种你最有可能用到的事后分析工具,一般是错误已出现或性能问题已经
用传统方法(客户抱怨大多属于此类)发现。
  继续之前的示例程序和它严重的内存泄露问题,在程序执行 30 分钟后,VisualVM 帮
我们绘制了如下图表:

  

  ▲图 5:程序初始运行的 VisualVM 内存图

  从这个图表,我们可以清晰地看到截止到 7:00pm,运行仅仅 10 分钟后,程序已经消
耗掉超过 1GB 的堆空间。又过了 23 分钟,JVM

已经到了它启动参数 Xmx3g 最大值,导

致程序响应缓慢,系统响应缓慢(持续的垃圾回收)和数量惊人的内存溢出错误。
  借助 jmap,我们定位了这种内存消耗攀升的原因。修复后,我们让程序重新运行于
VisualVM 的严格监测之下,观察到下面的情况: