由于一旦删除红色节点,其余的橙色节点都将无法被访问,这时候它们就会被 GC 回收掉。从这个角度上讲,它们是被红色节点所持有的,因此被命名为 “Retained Size”。
还有一个前面没有提到的数据维度。当您点击某个类名,界面中会显示这个类实例列表,这里有一列新数据 —— “Depth”:
“Depth” 是从 GC Root 到达这个实例的最短路径,图中的这些数字就是每个对象的深度 (Depth):
一个对象离 GC Root 越近,它就越有可能与 GC Root 有多条路径相连,也就越可能在垃圾回收中被保存下来。
以红色节点为例,如果从其左边来的任何一个引用被破坏,红色节点就会变成不可访问的状态并且被垃圾回收回收掉。而对于右边的蓝色节点来说,如果您希望它被垃圾回收,那您需要把左右两边的路径都破坏才行。
值得警惕的是,如果您看到某个实例的 “Depth” 为 1 的话,这意味着它直接被 GC root 引用,同时也意味着它永远不会被自动回收。
下面是一个示例 Activity,它实现了 LocationListener 接口,高亮部分代码 “requestLocationUpdates” 将会使用当前 Activity 实例来注册 locationManager。如果您忘记注销,这个 Activity 就会泄漏。它将永远都待在内存里,因为位置管理器是一个 GC root,而且永远都存在:
您能在 Memory Profiler 中查看这一情况。点击一个实例,Memory Profiler 将会打开一个面板来显示谁正在引用这个实例:
我们可以看到位置管理器中的 mListener 正在引用这个 Activity。您可以更进一步,通过引用面板导航至堆的引用视图,它可以让您验证这条引用链是否是您所预期的,也能帮您理解代码中是否有泄漏以及哪里有泄漏。
CPU Profiler
和 Memory Profiler 类似,CPU Profiler 提供了从另一个角度记录和分析应用关键性能数据的方法。
使用 CPU Profiler,首先要产生一些 CPU 的使用记录:
- 进入 Androi