Java HashSet<Long>应该占用多少内存

2022-09-03 07:00:06

我想使用a在内存中存储一大堆唯一数字。我计算了要消耗的近似内存(以64位指针大小表示):HashSet<Long>

Long 将占用 16 个字节的空间。因此,最初我将条目数乘以16以获得内存。但实际上,每个条目的内存远远超过16个字节。之后,我研究了实现。简而言之,在底层实现中,它实际上为每个哈希集条目存储了一个额外的虚拟对象(12个字节)。以及指向下一个条目的指针(8 个字节)。因此,每个条目额外允许 12+8 个字节。HashSet

因此,每个条目的总内存:16+12+8 = 36 字节。但是,当我运行代码并检查内存时,每个条目仍然远远超过36个字节。

我的问题(简而言之):需要多少内存(例如,在64位机器上)?HashSet


答案 1

您可以使用以下测试精确测量此大小:

    long m1 = Runtime.getRuntime().freeMemory();
    // create object (s) here
    long m2 = Runtime.getRuntime().freeMemory();
    System.out.println(m1 - m2);

使用 -XX:-UseTLAB 选项运行

在我的64位HotSpot上,空哈希集需要480字节。

为什么这么多?因为HashSet具有复杂的结构(顺便说一句,调试模式下的IDE有助于查看实际字段)。它基于HashMap(适配器模式)。因此,HashSet本身包含对HashMap的引用。HashMap 包含 8 个字段。实际数据位于节点数组中。节点具有:整型哈希;K 键;V值;节点下一个。HashSet 仅使用键,并将虚拟对象放在值中。


答案 2

对象的大小是一个实现细节。不能保证如果它在一个平台上是x字节,在另一个平台上它也是x字节。

Long如您所知,是装箱的,但 16 个字节是错误的。基元需要 8 个字节,但 周围的框的大小取决于实现。根据这个热点相关的答案开销单词和填充意味着一个盒装的4字节可以达到24字节!longlongint

该(特定于热点的)答案中提到的字节对齐和填充也适用于对象,这也将推动消耗增加。Entry


推荐