ArrayList对象的高内存消耗

时间:2015-12-17 15:49:06

标签: java memory-management arraylist amazon-s3 jvm

我创建了java对象(String的ArrayList),其大小为10 ^ 7到S3。每个条目(String)的大小为13个字节(12个字符)。这个文件的大小约为130MB。

现在,当我从S3(使用AmazonS3Client)将数据导入ArrayList对象时,机器前后的空闲内存分别为12090332712字节(11.26GB)和10334207976字节(9.62GB)。差异约为1.64GB左右。

现在的问题是String的ArrayList的内存消耗大约15个字节,大小10 ^ 7不应该如它所示的那么高。

一些观察结果:

  • 我们直接将数据从S3传输到ArrayList对象。甚至 如果ArrayList在达到当前容量时以1.5的速率增加, 它不应超过300MB
  • 尝试使用char []而不是String,因为char是原始类型并且会减少内存消耗,但情况也是如此。

请让我知道我错过了什么。

由于 阿达什讷

3 个答案:

答案 0 :(得分:2)

每当 foreach (RDOAttachment attachment in rdoMail.Attachments) { { if (!attachment.Hidden) { var savePath = tempPath + attachment.FileName; try { log.Trace("Attachment {0} saved : {1}", logIndex, attachment.FileName); attachment.SaveAsFile(savePath); resultList.Add(savePath); } catch (Exception exception) { log.ErrorException("Save Attachment As Exception", exception); log.Trace("Tryed save to path: ", savePath); } } } } } 达到当前限制时,就会创建一个新的更大的支持数组,并且会复制所有旧项目。这可能会导致大量数组只填充一半。< / p>

要避免这种情况,请使用git diff my_tag 或预先测量计数并创建具有完整容量的阵列。

答案 1 :(得分:1)

每个java对象都有开销。首先,每个对象都有一些标头,在64位架构上是16字节,可能更多。其次String由包装对象和包含数组组成。第三个字符表示为两个字节。

考虑到所有这些因素,每个字符串可能至少需要64个字节。此外,您需要存储所有字符串的数组和另一个半数大小的数组,这是在数组列表增加其大小之前使用的。另外还有一些用于反序列化的临时对象。

因此,覆盖范围非常大,您存储的数据越少,开销与您将看到的实际尺寸之间的比率就越大。

答案 2 :(得分:0)

“...... 15个字节的大小”这是你的数据部分。还有其他因素。

  • 对象标题:Java中的ALl对象记录其类
  • 对象锁定:Java中的所有对象都有自己的锁,因此占用空间
  • Java中的char是UTF-16 = 2字节
  • 内存对齐:内存中的对象不一定紧凑。如果一个对象在64位系统中只占用2个字节的内存,那么它实际上占用了64位(= 8个字节)的内存。

这些只是其中一些原因。可能还有其他人。