所以我创建了一个非常大的byte []数组,所以就像byte [50,000,000] [16] ..所以根据我的数学,800,000,000字节是0.8GB加上一些开销。 令我惊讶的是什么时候做
memoryBefore = runtime.totalMemory() - runtime.freeMemory()
它使用1.8GB的内存。当我指向一个分析器时,我得到了这个
https://www.dropbox.com/s/el9vlav5ylg781z/Screen%20Shot%202015-08-30%20at%202.55.00%20pm.png?dl=0
我可以看到大多数byte []是24字节而不是16,正如预期的那样,我看到相当大的字节[]大小为472或更多..有谁知道这里发生了什么?
感谢您阅读
答案 0 :(得分:4)
所有对象都有维护对象的开销,“类型”又称Class
等信息。请参阅What is the memory consumption of an object in Java?。
数组也有length
,并且64位Java中的开销可能更大。
由于您要分配50,000,000个16字节的数组,因此获得50_000_000 * (16 + overhead) + (overhead + 50_000_000 * pointerSize)
。第二部分是数组的外部数组。
根据您的要求,您可以通过以下两种方式之一来改进:
将二维数组的索引翻转为byte[16][50_000_000]
。这减少了50,000,001到17的开销,减少了外部阵列的大小。
使用单个数组byte[16 * 50_000_000]
并自行进行偏移逻辑。这将使您的16个字节保持连续并消除所有开销。
答案 1 :(得分:1)
我可以看到大多数byte []都是24bytes而不是16
除了保存对象字段的空间之外,Java中的对象还有几个标题信息。在数组的情况下,还有一个单词来保存数组的length
字段。 length
实际上需要4个字节('cos length
是int
),但JVM最有可能与您平台上的8字节边界对齐。
如果您看到占用24个字节的16字节数组,那么空间的计算很可能包括(仅)length
字。
(请注意,对象/数组头占用的实际空间是JVM和特定于平台的。)
...我看到相当大的字节[]大小为472或更大。
那些是无关的。如果代码的其他部分没有显式创建它们,则很可能是由Java运行时库创建的。