java堆转储显示的保留堆内存少于预期

java堆转储显示的保留堆内存少于预期,java,Java,我正在检查应用程序的堆转储。应用程序有一个java.util.concurrent.ConcurrentHashMap,其中键类型是java.lang.String,值是一个用户定义的类,带有字节[]字段 我添加了16000个键,每个键有30个字符,值的字节数组是3000字节。所以我预计并发hashmap的总保留堆大小为48MB(16000*3000) 但是堆转储中的值是24MB。当我进一步检查时,我发现有许多条目如下。这些条目具有HashMap节点的保留大小,远远小于键和值的保留大小之和 如何

我正在检查应用程序的堆转储。应用程序有一个
java.util.concurrent.ConcurrentHashMap
,其中键类型是
java.lang.String
,值是一个用户定义的类,带有
字节[]
字段

我添加了16000个键,每个键有30个字符,值的字节数组是3000字节。所以我预计并发hashmap的总保留堆大小为48MB(16000*3000)

但是堆转储中的值是24MB。当我进一步检查时,我发现有许多条目如下。这些条目具有HashMap节点的保留大小,远远小于键和值的保留大小之和

如何理解这种差异

Class Name                                                                             | Shallow Heap | Retained Heap
----------------------------------------------------------------------------------------------------------------------
[5490] java.util.concurrent.ConcurrentHashMap$Node @ 0x6c6a23910                       |           32 |           136
|- <class> class java.util.concurrent.ConcurrentHashMap$Node @ 0x6c71bc320 System Class|            0 |             0
|- key java.lang.String @ 0x6c6a23930  /data-node-3-10/parent2/child2                  |           24 |           104
|- val org.apache.zookeeper.server.DataNode @ 0x6c6a23998                              |           32 |         3,304
----------------------------------------------------------------------------------------------------------------------
类名|浅堆|保留堆
----------------------------------------------------------------------------------------------------------------------
[5490]java.util.concurrent.ConcurrentHashMap$Node@0x6c6a23910 | 32 | 136
|-类java.util.concurrent.ConcurrentHashMap$Node@0x6c71bc320系统类| 0 | 0
|-key java.lang.String@0x6c6a23930/data-node-3-10/parent2/child2 | 24 | 104
|-val org.apache.zookeeper.server.DataNode@0x6c6a23998 | 32 | 3304
----------------------------------------------------------------------------------------------------------------------
PS:我手头的任务是找出系统配置和内存使用之间的关系

编辑:对于许多其他条目,值如下所示。HashMap节点(3160)的保留大小包含节点键(128)+值(3000)的保留大小。 但对于某些条目(例如,如上所示),对于键和值的保留大小分别为104和3304的节点,它似乎不正确(136)

Class Name                                                                             | Shallow Heap | Retained Heap
----------------------------------------------------------------------------------------------------------------------
[9706] java.util.concurrent.ConcurrentHashMap$Node @ 0x6c6a1ab98                       |           32 |         3,160
|- <class> class java.util.concurrent.ConcurrentHashMap$Node @ 0x6c71bc320 System Class|            0 |             0
|- key java.lang.String @ 0x6c6a1abb8  /data-node-0-10/parent1/child2/grandchild1      |           24 |           128
|- val org.apache.zookeeper.server.DataNode @ 0x6c6a1ac38                              |           32 |         3,000
----------------------------------------------------------------------------------------------------------------------
类名|浅堆|保留堆
----------------------------------------------------------------------------------------------------------------------
[9706]java.util.concurrent.ConcurrentHashMap$Node@0x6c6a1ab98 | 32 | 3160
|-类java.util.concurrent.ConcurrentHashMap$Node@0x6c71bc320系统类| 0 | 0
|-key java.lang.String@0x6c6a1abb8/data-node-0-10/parent1/child2/孙子1 | 24 | 128
|-val org.apache.zookeeper.server.DataNode@0x6c6a1ac38 | 32 | 3000
----------------------------------------------------------------------------------------------------------------------

没有代码,特别是对于您的数据类,我们无法猜测。我怀疑,由于这是一个托管环境,而不仅仅是一个免费的普通JVM应用程序,重复数据消除可能正在进行。或者,根据你从哪里得到的报告(你没有说,也没有提供单位),它可能只计算地图条目本身的成本,而不是下游引用的成本。它实际上是Zookeeper。我经营一个三人合奏团。并在创建16000个条目后为其中一个成员进行堆转储。由于该值是一个
字节[]
,可能没有进行重复数据消除?而且所有的键都是唯一的。