Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中计算HashMap内存使用率?_Java_Memory Management_Garbage Collection_Hashmap_Jvm - Fatal编程技术网

如何在Java中计算HashMap内存使用率?

如何在Java中计算HashMap内存使用率?,java,memory-management,garbage-collection,hashmap,jvm,Java,Memory Management,Garbage Collection,Hashmap,Jvm,在一次采访中,我被要求计算HashMap的内存使用量,以及如果你有200万个项目,它估计会消耗多少内存 例如: Map <String,List<String>> mp=new HashMap <String,List<String>>(); 如何估计Java中此HashMap对象的内存使用情况?如果不知道所有字符串是什么,以及每个列表中有多少项,或者不知道这些字符串是否都是唯一引用,则无法提前知道 唯一可以确定的方法是将整个过程序列化为字节数组

在一次采访中,我被要求计算
HashMap
的内存使用量,以及如果你有200万个项目,它估计会消耗多少内存

例如:

Map <String,List<String>> mp=new HashMap <String,List<String>>();

如何估计Java中此HashMap对象的内存使用情况?

如果不知道所有字符串是什么,以及每个列表中有多少项,或者不知道这些字符串是否都是唯一引用,则无法提前知道


唯一可以确定的方法是将整个过程序列化为字节数组(或临时文件),并查看到底有多少字节。

简短的答案是

要找出一个对象有多大,我会使用探查器。例如,在工具包中,您可以搜索对象,然后让它计算其深度大小。如果对象是独立的,并且是对象的保守大小,这将使您大致了解将使用多少内存

诡辩

如果对象的某些部分在其他结构(例如字符串文字)中重复使用,则丢弃它不会释放这么多内存。事实上,丢弃对HashMap的一个引用可能根本不会释放任何内存

那连载呢

序列化对象是获得估计值的一种方法,但由于序列化开销和编码在内存和字节流中是不同的,因此可能会出现很大的偏差。使用多少内存取决于JVM(以及它是否使用32/64位引用),但序列化格式总是相同的

e、 g

在Sun/Oracle的JVM中,一个整数可以包含16个字节的头,4个字节的数字和4个字节的填充(对象在内存中是8字节对齐的),总共24个字节。但是,如果序列化一个整数,需要81个字节,序列化两个整数,需要91个字节。i、 e.第一个整数的大小膨胀,第二个整数小于内存中使用的整数

字符串是一个更复杂的例子。在Sun/Oracle JVM中,它包含3个
int
值和一个
char[]
引用。因此,您可能会假设它使用16字节的头加上3*4字节作为
int
s,4字节作为
char[]
,16字节作为
char[]
的开销,然后每个char使用两个字节,与8字节的边界对齐

什么标志可以更改大小

如果您有64位引用,则
char[]
引用的长度为8字节,导致4字节的填充。如果您有64位JVM,则可以使用
+XX:+UseCompressedOops
来使用32位引用。(因此,仅看JVM位大小并不能告诉您其引用的大小)

如果您有
-XX:+UseCompressedStrings
,JVM将尽可能使用byte[]而不是char数组。这会稍微降低应用程序的速度,但会显著提高内存消耗。当使用字节[]时,消耗的内存为每个字符1字节。;)注意:对于4字符字符串,如示例中所示,由于8字节的边界,使用的大小相同

你所说的“尺寸”是什么意思?

正如已经指出的,HashMap和List更为复杂,因为即使不是全部,也可以重用许多字符串,可能是字符串文本。你所说的“大小”取决于它的使用方式。i、 e.结构单独使用多少内存?如果该结构被丢弃,将释放多少空间?如果复制结构,将使用多少内存?这些问题可能有不同的答案

没有分析器你能做什么?

如果您可以确定可能的保守尺寸足够小,那么确切的尺寸并不重要。保守的情况可能是从头开始构造每个字符串和条目。(我只说可能,因为HashMap可以容纳10亿个条目,即使它是空的。具有单个字符的字符串可以是具有20亿个字符的字符串的子字符串)

您可以执行System.gc(),获取可用内存,创建对象,执行另一个System.gc(),然后查看可用内存减少了多少。您可能需要多次创建对象并取平均值。重复这个练习很多次,但它可以给你一个公平的想法


(顺便说一句,System.gc()只是一个提示,Sun/Oracle JVM默认情况下每次都会执行完整的gc)

我认为应该澄清这个问题,因为HashMap的大小和HashMap+HashMap包含的对象的大小之间存在差异

如果您考虑HASMAP的大小,在您提供的示例中,HASMAP存储对字符串“ABY”的一个引用和对该列表的一个引用。因此,列表中的多个元素并不重要。值中仅存储对列表的引用

在32位JVM中,在一个映射条目中,有4个字节用于“aby”引用+4个字节用于列表引用+4个字节用于映射条目的“hashcode”int属性+4个字节用于映射条目的“next”属性

您还可以添加4*(X-1)字节引用,其中“X”是调用构造函数时HashMap创建的空桶数
newHashMap()
. 根据统计,应该是16

还有loadFactor、modCount、threshold和size,它们都是基本的int类型(16字节以上)和header(8字节)

最后,上面的HashMap的大小是4+4+1+(4*15)+16+8=93字节

这是基于HashMap拥有的数据的近似值。我认为面试官可能有兴趣了解您是否了解HashMap的工作方式(例如,默认构造函数为Map条目创建16个bucket的数组,HashMap中存储的对象的大小不会影响HashMap的大小,因为它只存储引用)

HashMap被广泛使用,在某些情况下,它应该是w
key   value
----- ---------------------------
abc   ['hello','how']
abz   ['hello','how','are','you']