练习 1.3:分析“疑似泄漏对象”
在开始之前,必须已完成练习 1.2:捕获堆转储。
在此练习中,将首先生成一个显示似乎在泄漏的对象(比如数组、向量和会话)的列表。这些是“疑似泄漏对象”。
然后分析此列表以识别泄漏。
生成“疑似泄漏对象”列表
要生成该列表:
- 按照“疑似泄漏对象”视图中的指示信息,单击“分析泄漏”工具栏按钮
。
打开“选择泄漏分析选项”对话框。
- 在对话框中,确保选中了两个堆转储的复选框。
注意:“阈值”值缺省设置为 20。这意味着只显示似然估计值为 20 或以上的“疑似泄漏对象”。
(有关似然估计值的更多信息在此练习稍后提供。)
- 单击确定以生成列表。Software Development Platform 右下角的指示器报告它正在查找“疑似泄漏对象”。
“疑似泄漏对象”视图概述
过程完成时,“疑似泄漏对象”视图显示“疑似泄漏对象”列表。
每个“疑似泄漏对象”都有介于 100 和 1 之间的似然估计值,最疑似的泄漏对象的值为 100。
其它“疑似泄漏对象”相应地分了等级,并且按似然估计的降序列出。
(堆比较算法基于泄漏的大小以及在两个堆转储之间时间间隔的增长计算似然估计值。)
概要分析运行的阈值设置为 20;
不显示所有似然估计值为 19 或以下的“疑似泄漏对象”。
此视图提供每个“疑似泄漏对象”的以下数据:
- 泄漏源。这是保存对潜在泄漏对象的引用的顶级根对象。
- 容器类型。这是保存泄漏对象的收集对象。泄漏最可能在收集对象中发生,比如向量和列表。
- 泄漏类型。这是泄漏对象的类型。
- 泄漏数。此值代表容器对象中在“泄漏类型”栏指定类型的对象数。
这些对象可能又会引入其它对象。“泄漏对象”和“泄漏字节”栏中包括这些引用的对象。
- 泄漏字节。
- 泄漏对象。
分析并识别泄漏
要识别泄漏:
- 在“疑似泄漏对象”视图中,查看似然估计值为 100 的“疑似泄漏对象”的数据:
- 泄漏源是 TestThreeTierQueue.<ObjectID>。
- 容器类型是Vector。
- 此向量是泄漏字符串。换句话说,向量保存字符串的引用,从泄漏数和泄漏的字节数进行判断,
应释放该向量,从而垃圾回收可以释放内存。
(泄漏数和泄漏的字节数在每次运行程序时可能不同,这依赖于捕获堆转储的计时。)
- 双击“疑似泄漏对象”。打开“对象引用图”视图,并显示“疑似泄漏对象”的图形数据。
(注意可能要耗费一段时间准备显示堆转储。)
- 检验对象引用图。注意以下几点:
- 此图形突出显示由引用连接到潜在泄漏(泄漏源),向下贯穿 SecondaryQueue,然后到向量,最终连接到泄漏的字符串集的对象。这提供了泄漏类型的可视图像。
- 在图形中,有一个由 Vector(泄漏涉及的容器类型)引用的 Object 数组,且 Object 数组引用泄漏 String 对象。
- 将光标停留在连接 Object 数组和 String 的路径上,并阅读显示的工具提示:它将显示一个等于在“疑似泄漏对象”视图中显示的“泄漏数”的“计数”,所以这是已识别为泄漏的字符串的集合。
- 在“对象引用图”中,双击 String 对象。打开“对象详细信息”视图。将显示 String 对象的所有详细信息,包括引用它的所有对象,以及它随后引用的所有对象。注意,在“对象详细信息”视图中,可以通过单击对象之一向上浏览引用者,
或通过单击对象之一向下浏览被引用对象(此对象引用的对象)。
您已发现了什么?现在您已了解第二级队列是泄漏对象,并且它泄漏的原因在于 Vector 对象持续引用多个 String 对象。
现在您就可以开始练习 1.4:修正内存泄漏。