图 2. 在 Memory Analyzer 中分析 Java 集合的填充率
在判断当前大小超出需要的大小的集合时,图 2 中选择的 Collection Fill Ratio 查询是最有用的。您可以为该查询指定多种选项,这些选项包括: 对象:您关注的对象类型(集合) 分段:用于分组对象的填充率范围
将对象选项设置为 \"java.util.Hashtable\"、将分段选项设置为 \"10\",之后运行查询将得到如图 3 所示的输出结果:
图 3. 在 Memory Analyzer 中对 Hashtable 的填充率分析
图 3表明,在 java.util.Hashtable 的 262,234 个实例中,有 127,016 (48.4%) 的实例完全未空,几乎所有实例都仅包含少量条目。
随后便可识别这些集合,方法是选择结果表中的一行,右键单击并选择 list objects -> with incoming references,查看哪些对象拥有这些集合,或者选择 list objects -> with outgoing references,查看这些集合中包含哪些条目。图 4展示了查看对于空 Hashtable 的传入引用的结果,图中展开了一些条目:
图 4. 在 Memory Analyzer 中对于空 Hashtable 的传入引用的分析
图 4 表明,某些空 Hashtable 归
javax.management.remote.rmi.NoCallStackClassLoader 代码所有。 通过查看 Memory Analyzer 左侧面板中的 Attributes 视图,您就可以看到有关 Hashtable 本身的具体细节,如图 5 所示:
图 5. 在 Memory Analyzer 中检查空 Hashtable
图 5表明,Hashtable 的大小为 11(默认大小),而且完全是空的。 对于 javax.management.remote.rmi.NoCallStackClassLoader 代码,可以通过以下方法来优化集合使用:
延迟分配 Hashtable:如果 Hashtable 为空是经常发生的普遍现象,那么仅在存在需要存储的数据时分配 Hashtable 应该是一种合理的做法。
将 Hashtable 分配为准确的大小:由于使用默认大小,因此完全可以使用更为准确的初始大小。
这些优化是否适用取决于代码的常用方式以及通常存储的是哪些数据。 PlantsByWebSphere 示例中的空集合 表 2 展示了分析 PlantsByWebSphere 示例中的集合来确定哪些集合为空时的分析结果: 表 2. WebSphere Application Server v7 中 PlantsByWebSphere 的空集合使用量 集合类型 实例数量 空实例 空实例百分比 Hashtable 262,234 127,016 48.4 WeakHashMap 19,562 19,465 99.5 HashMap 10,600 7,599 71.7 ArrayList 9,530 4,588 48.1 HashSet 1,551 866 55.8 Vector 1,271 622 48.9 总计 304,748 160,156 52.6 表 2 表明,平均而言,超过 50% 的集合为空,也就是说通过优化集合使用能够实现可观的内存占用节约。这种优化可以应用于应用程序的各个级别:应用于 PlantsByWebSphere 示例代码中、应用于 WebSphere Application Server 中,以及应用于 Java 集合类本身。 在 WebSphere Application Server 版本 7 与版本 8 之间,我们做出了一些努力来改进 Java 集合和中间件层的内存效率。举例来说,java.util.WeahHashMap 实例的开销中,有很大一部分比例源于其中包含用来处理弱引用的 java.lang.ref.ReferenceQueue 实例。图 6 展示了 32 位 Java 运行时中的一个 WeakHashMap 的内存布局: 图 6. 32 位 Java 运行时中的一个 WeakHashMap 的内存布局
图 6表明,ReferenceQueue 对象负责保留占用 560 字节的数据,即便在 WeakHashMap 为空、不需要 ReferenceQueue 的情况下也是如此。对于 PlantsByWebSphere 示例来说,在空 WeakHashMap 的数量为 19,465 的情况下,ReferenceQueue 对象将额外增加 10.9MB 的非必要数据。在 WebSphere Application Server 版本 8 和 IBM Java 运行时的 Java 7 发布版中,
WeakHashMap 得到了一定的优化:它包含一个 ReferenceQueue,这又包含一个 Reference 对象数组。该数组已经更改为延迟分配,也就是说,仅在向 ReferenceQueue 添加了对象的情况下执行分配。
因篇幅问题不能全部显示,请点此查看更多更全内容