java - 填充 Hashmap 时超出 GC 开销限制

标签 java garbage-collection hashmap

当我的 java 程序启动时,它会用数千个对象填充 HashMap 。键是一个字符串,值是一组对象。

程序正在全速运行,并在达到大约 10000 个键时抛出内存不足异常:超出 GC 开销限制。

我读到可能是底层数组必须不断调整大小。但是我希望能够在不简单地增加堆大小的情况下解决这个问题。

谢谢!

最佳答案

您需要对数据大小进行建模,加上 HashMap 的每个元素开销,以确定您的堆要求。

为了简单起见,我假设您正在使用压缩的 OOPS(OOP = 普通对象指针)运行 64 位 JVM。这为每个对象提供了一个 12 字节的 header 和一个 4 字节的对象引用。我将进一步假设您正在使用默认加载因子为 0.75 的 HashMap

对于 10,000 个元素,表格大小最小为 10,000/0.75 = 13,333。然而,表的大小始终是 2 的幂,所以它可能有 16,384 长。这给出了 65,536 字节 -- 64KB。

存储在 HashMap 中的每个元素还需要创建一个内部 Node 对象,它有四个 4 字节的字段(hash、key、value、next)加上对象头 12 个字节,每个 Node 对象有 28 个字节。如果有 10,000 个元素,则为 280KB。

HashMap 表大小加上内部 Node 对象因此需要 344KB 的开销来存储 10,000 个键值对。那不会导致您内存不足。更改 HashMap 的初始容量将减少调整大小的复制开销,但与数百 MB 或几 GB 的典型堆大小相比,它占用的临时额外内存量可以忽略不计。

如果您的堆大小为 1 GB,并且您在 10,000 个映射条目时内存不足,那么每个键值对大约需要 100 KB。除非您大幅增加堆大小,或者减少每个键值对的大小,或者两者的某种组合,否则您将无法加载几百万个键。

关于java - 填充 Hashmap 时超出 GC 开销限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36343813/

相关文章:

java - 带有java的Android IP地址

c# - 处置自定义对象

java - 如何在HashMap中实现入门级锁定?

scala - Scala 中的多键映射

android - 如何正确地将数据添加到 Hashmap

java - 尚未被 GC 删除的对象

java - 如何使 Websphere App 将每个应用程序日志条目重定向到不同的文件?

java - Guava 或其他地方是否有Identity SetMultimap?

c# - 未分配给变量的类实例是否会过早被垃圾回收?

java - 在循环期间动态写入 CSV