本文主要介绍如何如何利用在使用JProfiler时意识到内存泄漏以及查找内存泄漏的几种方法。
方法/步骤
-
JProfiler的内存视图会话提供了内存使用情况的动态更新视图以及分配点的信息视图。所有的视图都有几个聚集层并且能够显示现有存在的对象和作为垃圾回收的对象。本文主要介绍如何意识到内存泄漏以及查找内存泄漏的几种方法。
-
意识到内存泄漏
怀疑内存泄漏的第一步就是查看 "Memory"和"Recorded objects" 遥感勘测视图。当应用程序出现内存泄漏时,视图中会显示出带有震荡的线性积极趋势。如果没有这样的线性趋势,您的应用程序可能只是消耗了大量的内存,而不是内存泄漏。处理方法很简单,找出占用大量内存的类或阵列,尽量减少类或阵列的数量。
-
使用差异缩小内存泄漏
查找内存泄漏的起源的第一步就是查找对象视图和所记录的对象视图的差异。简单的内存泄漏可以利用差分功能来追查。
观察对象视图和所记录的对象视图的差异,然后找出该差异是有哪些类引起的。然后,当切换到热点视图时,选择问题类别,然后观察问题实例所分配到的差异列。此时,知道实例创建的方法。
-
堆遍历器和内存泄漏
当获取了一堆快照时,首先你必须创建一个带有对象实例的对象集。如果你在动态内存视图中已经收窄内存泄漏原因的范围,你可以使用 "show selection in heap walker"来保存操作并启动堆遍历器。
-
利用对象视图找出内存泄漏原因
大多数的内存泄漏可以被追溯到对象集群。这将产生一些大的retained size的对象。最大的对象视图列出了带有最大retained size的对象。你可以利用该树形向下钻取从而发现错误引用。
-
使用参考图找到内存泄漏的原因
找出内存泄漏的核心工具是堆遍历器中的参考图。依次打开传入引用,你可能会立即发现一个错误引用。在复杂的系统中,这往往是不可能的。在这种情况下,你必须要找到一个或多个"garbage collector roots"。Garbage collector roots是JVM中的点,不受垃圾回收机制的约束。当你选择了传入引用或图形中的一个对象时,顶部的[Show path to GC root] 按钮被启用。
-
garbage collector roots非常多,若全部显示它们,可能会造成大量堆积,如图所示。此外,查找garbage collector roots也很耗时。 如果找到成千上万的roots,计算的时间很长而且会占用大量内存。为了防止这些问题,最好开始时从单个garbage collector root 开始查找,然后根据利用 UP to roots 根据需要慢慢增加garbage collector root。
-
garbage collector root 的链条可以很长,如图所示:
-
使用cumulated references views以查找内存泄漏的原因
在某些情况下,您可能无法成功地缩小对象设置的规模。你的对象集中可能仍包含了大量的实例或者在此情况下,使用参考图不可能会提供任何见解。这时,堆遍历器的引用视图中的 the cumulated reference tables 就可排上用场了。cumulated incoming reference table显示了当前对象集中所有可能的引用类型:
从引用类型中,你就可以缩小对象集。例如,您可能知道那些引用类型是正常的,那些是不正常的。