我的应用程序需要大约 10 GB 的 RAM 用于特定输入,而对于常规输入,大约 1 GB 就足够了。使用 JProfiler 进行更仔细的分析表明(在 GC 之后)标准类使用了相当多的内存java.util.*
:
LinkedHashMap$Entry
, HashMap$Entry[]
, LinkedHashMap
, HashMap$KeySet
, HashMap$EntrySet
, LinkedHashSet
, TreeMap$Entry
, 和TreeMap
(按此顺序)和相关类。以下条目是我自己代码中的一个类,其中实例的数量和使用的内存量似乎非常合理。
在总堆使用量约为 900 MB 的情况下,我Size
在视图中看到以下条目All Objects
:
LinkedHashMap$Entry
: 418 兆字节HashMap$Entry[]
: 178 兆字节LinkedHashMap
:124兆字节HashMap$KeySet
: 15 兆字节
使用的内存LinkedHashMap
似乎太高了,即使考虑到LinkedHashSet
each 由LinkedHashMap
.
我在 JProfiler 中记录了对象分配并观察了Allocation Hot Spots
for LinkedHashMap
. 在那里,我看到了我不理解的条目:
- 第三个条目显示了一个热点(分配内存的 6.5%),名为
X.<init>
whereX
是我自己代码中的一个类。该方法的构造函数与 . 没有任何关系LinkedHashMap
。在此进入到Thread.run
最后显示从 6.5% 到 5.8% 的缓慢下降Thread.run
。我的代码可能有什么问题X
?为什么显示在这里? - 大约 8% 的已分配内存显示在名为 的热点中
java.util.HashSet.iterator
。沿着百分比最高的路径(第一个条目:2.8%)跟随这个条目,我在代码中得到了几个方法,直到最后java.lang.Thread.run
显示(2.8%)。这是什么意思?据我所知,该Thread.run
方法不会创建LinkedHashMap
. 与iterator
方法有什么关系?
一般来说,我如何找到保留对(很多)LinkedHashMap
对象的引用的代码?使用 Heap Walker,我只能看到很多这样的实例,但看不到任何模式(即使在观察到 GC 根的路径时)。在我的实验中,所有实例似乎都井然有序。
可能重要的事情:
- 我的应用程序构造了一个结果(用于进一步处理),并且对于这种构造,观察到了高内存使用情况。
LinkedHashMap
构造不断创建对象,因此不可能等待一个稳定点然后观察每个创建的对象。 - 我有很好的计算机可供调试(最多 48 个内核和 192 GB 的 RAM,甚至可能更多)。
- java 版本“1.7.0_13”(Java(TM) SE 运行时环境(构建 1.7.0_13-b20),Java HotSpot(TM) 64 位服务器 VM(构建 23.7-b01,混合模式))
- JProfiler 7.2.2(内部版本 7157),许可