【问题标题】:Java object memory size of a set of strings一组字符串的Java对象内存大小
【发布时间】:2014-08-06 20:52:09
【问题描述】:

我有一个包含 1000 个字符串的哈希集。每个字符串的大小为 10。

您能告诉我将其存储在内存中所需的确切字节数吗?适用于 32 位和 64 位 VM。

你能解释一下计算方法吗?

【问题讨论】:

  • @SotiriosDelimanolis 应该没关系,因为String 在内部使用char[]size() 返回该数组的长度?
  • 如果你想自己找出答案,可以使用Instrumentation界面中的getObjectSize()
  • @user3580294 是的,好点。 (请设置您的姓名。我一直将您与刚创建帐户的其他用户混淆。)
  • 说实话,我不确定您是否可以手动计算...对象属性在 8 字节边界上对齐,并进行了一些重新排列以节省内存,并且全部在我不确定有多少人愿意做大量的工作......

标签: java memory-management


【解决方案1】:

因为我没有生命,所以我呈现无聊的结果。请注意,由于愚蠢的错误等,这几乎可以保证是不准确的。使用this 寻求帮助,但我不太确定准确性。我可以阅读 JVM 规范,但我手上没有那么太多空闲时间。

这个计算变得相当复杂,因为关注的对象内部存在大量字段,加上我对对象有多少开销以及填充的去向有一些不确定性。如果内存服务,对象有 8 个字节保留给头。顺便说一下,这都是针对 64 位 VM 的。我认为它与 32 位 VM 之间的唯一区别是引用的大小。

如何做到这一点的总结:获取源代码,并递归地添加所有字段所需的空间。需要了解 VM 的工作原理以及实现的工作原理。

String 开始。 String 定义:

  1. 对象头 - 8 个字节
  2. long serialVersionUID - 8 个字节
  3. int hash - 4 字节 + 4 字节填充
  4. char[] value(在您的情况下设置为 char[10])- 8 个字节供参考
  5. ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0] - 8 个字节供参考

char[10] 定义:

  1. 对象头 - 8 个字节
  2. int length - 4 个字节
  3. char x10 - 2 字节 * 10 = 20 字节

ObjectStreamField[0] 定义:

  1. 对象头 - 8 个字节
  2. int length - 4 字节 + 4 字节填充

长度为 10 的单个 String 的总长度:88 个字节

长度为 10 的 1000 Strings 的总数:88000 字节。


HashSet 定义:

  1. 对象头 - 8 个字节
  2. long serialVersionUID - 8 个字节
  3. Object PRESENT - 8 个字节
  4. HashMap<E, Object> map - 8 个字节

HashMap 定义(在 Java 8 中)(忽略按需创建的内容,例如 EntrySet):

  1. 对象头 - 8 个字节
  2. long serialVersionUID - 8 个字节
  3. int DEFAULT_INITIAL_CAPACITY - 4 个字节
  4. int MAXIMUM_CAPACITY - 4 个字节
  5. int TREEIFY_THRESHOLD - 4 个字节
  6. int UNTREEIFY_THRESHOLD - 4 个字节
  7. int MIN_TREEIFY_CAPACITY - 4 个字节
  8. int size - 4 个字节
  9. int modcount - 4 个字节
  10. int threshold - 4 个字节
  11. float DEFAULT_LOAD_FACTOR - 4 个字节
  12. float loadFactor - 4 个字节
  13. Node<K, V>[] table - 8 个字节

Node 定义:

  1. 对象头 - 8 个字节
  2. int hash - 4 字节 + 4 字节填充
  3. K key - 8 个字节
  4. V value - 8 个字节
  5. Node<K, V> next - 8 个字节

Node<K, V>[] 的大小应该是 2048,如果我记得 HashMap 是如何工作的。所以它定义:

  1. 对象头 - 8 个字节
  2. int length - 4 字节 + 4 字节填充
  3. Node<K, V> 参考 * 2048 - 8 字节 * 2048 = 16384 字节。

所以HashSet 应该是:

  1. HashSet 32 个字节
  2. 64 字节,仅用于 HashMap
  3. Node<K, V> 内每个 Node<K, V>[] 40 字节 * 1000 个节点 = 40000 字节
  4. Node<K, V>[]HashMap 内的 16400 字节

总计:HashSet 的 56496 字节,不考虑 String 的内容


所以至少根据我的计算,占用的总空间应该在 144496 字节左右——大约 141 KB(对于迂腐的人来说是 kibibytes)。老实说,这似乎有点偏小,但这是一个开始。

我目前无法让Instrumentation 接口工作,所以我无法仔细检查。但是,如果有人知道他/她在做什么,请发表评论指出我的错误。

【讨论】:

  • 如果字符串不是唯一的,它们可能会被池化,因此使用的空间更少。这取决于 JVM 的实现。
猜你喜欢
  • 2011-11-01
  • 1970-01-01
  • 2011-01-04
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多