我有一个1000字符串的哈希集。每个字符串的大小为10。
你能告诉我在内存中存储它所需的确切字节数吗?适用于32位和64位虚拟机。
你能解释计算这个的方法吗?
答案 0 :(得分:7)
因为我没有生命,所以我呈现了无聊的结果。请注意,由于愚蠢的错误等原因,这几乎可以保证不准确。使用this求助,但我对准确性不太了解。我可以读取JVM规范,但我没有那个空闲时间。
由于所关注对象中存在大量字段,这个计算变得相当复杂,加上我对于对象有多少开销以及填充位置的不确定性。如果内存服务,则对象具有为标头保留的8个字节。顺便说一下,这对于64位VM来说都是如此。我认为,只有32位虚拟机之间的差异就是参考的大小。
如何执行此操作的摘要:获取源代码,并递归地添加所有字段所需的空间。需要了解VM如何工作以及实现如何工作。
从String
开始。 String
定义:
long serialVersionUID
- 8个字节int hash
- 4个字节+ 4个字节填充char[] value
(在您的情况下设置为char[10]
) - 8个字节供参考ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]
- 8个字节供参考 char[10]
定义:
int length
- 4个字节char
x10 - 2个字节* 10 = 20个字节 ObjectStreamField[0]
定义:
int length
- 4个字节+ 4个字节填充长度为10:88字节的单个String
的总计
1000 String
的总计,长度为10:88000字节。
HashSet
定义:
long serialVersionUID
- 8个字节Object PRESENT
- 8个字节HashMap<E, Object> map
- 8个字节 HashMap
定义(在Java 8中)(忽略按需创建的内容,如EntrySet
):
long serialVersionUID
- 8个字节int DEFAULT_INITIAL_CAPACITY
- 4个字节int MAXIMUM_CAPACITY
- 4个字节int TREEIFY_THRESHOLD
- 4个字节int UNTREEIFY_THRESHOLD
- 4个字节int MIN_TREEIFY_CAPACITY
- 4个字节int size
- 4个字节int modcount
- 4个字节int threshold
- 4个字节float DEFAULT_LOAD_FACTOR
- 4个字节float loadFactor
- 4个字节Node<K, V>[] table
- 8个字节 Node
定义:
int hash
- 4个字节+ 4个字节填充K key
- 8个字节V value
- 8个字节Node<K, V> next
- 8个字节Node<K, V>[]
是如何工作的,那么 HashMap
的大小应该是2048。所以它定义了:
int length
- 4个字节+ 4个字节填充Node<K, V>
引用* 2048 - 8字节* 2048 = 16384字节。所以HashSet
应该是:
HashSet
HashMap
Node<K, V>
内每Node<K, V>[]
个40个字节* 1000个节点= 40000个字节Node<K, V>[]
HashMap
的16400字节
醇>
总计:HashSet
的56496字节,未考虑String
内容
因此,至少根据我的计算,所占用的总空间应该在144496字节左右 - 大约141千字节(迂腐的kibibytes)。说实话,这似乎不仅仅是一个小问题,但它是一个开始。
我目前无法让Instrumentation
界面正常工作,所以我无法仔细检查。但如果有人知道他/她正在做什么评论指出我的错误将是受欢迎的。