简体   繁体   English

如何计算 java 数组 memory 使用量

[英]how calculate java array memory usage

If I have:如果我有:

int c[] = new int[10];

and

int a[][] = new int[2][3];

and in generally并且通常

an n*m*..*j array一个n*m*..*j数组

how can I calculate the real memory usage considering also the references variables?考虑到参考变量,我如何计算真正的 memory 使用量?

I know I'm kinda late to the party, but it's really not extremely hard to compute the memory footprint.我知道我参加聚会有点晚了,但计算内存占用量真的不是很难。

Lets take your first example: int c[] = new int[N];让我们举你的第一个例子: int c[] = new int[N];

According to the 64-bit memory model, an int is 4 bytes, so all the elements will be 4*N bytes in size.根据 64 位内存模型,一个 int 是 4 个字节,所以所有元素的大小都是 4*N 个字节。 In addition to that, Java has a 24 bytes array overhead and there's also 8 bytes for the actual array object.除此之外,Java 有 24 个字节的数组开销,实际数组对象还有 8 个字节。 So that's a total of 32 + 4 * N bytes.所以总共有 32 + 4 * N 个字节。

For a 2 dimensional array: int a[][] = new int[N][M];对于二维数组: int a[][] = new int[N][M];

It's basically the same just that each element in the first array is another array of size M, so instead of 4 we have 32 + 4 * M, so the total size is 32 + (32 + 4 * M) * N.基本相同,只是第一个数组中的每个元素都是另一个大小为 M 的数组,因此我们有 32 + 4 * M,而不是 4,因此总大小为 32 + (32 + 4 * M) * N。

It's true that a generalization for D dimensions is pretty complicated, but you get the idea.确实,D 维的泛化非常复杂,但您明白了。

If you want an accurate answer, you can't.如果你想要一个准确的答案,你不能。 At least not in any easy way.至少不是以任何简单的方式。 This thread explains more. 这个线程解释了更多。

The trouble with Bragaadeesh's and Bakkal's answers are that they ignore overhead. Bragaadeesh 和 Bakkal 的答案的问题在于他们忽略了开销。 Each array also stores things like the number of dimensions it has, how long it is and some stuff the garbage collector uses.每个数组还存储诸如它的维数、长度以及垃圾收集器使用的一些东西。

For a simple estimate, you should be fine by using the calculations from the other answers and adding 100-200 bytes.对于简单的估计,使用其他答案中的计算并添加 100-200 字节应该没问题。

you'll probably get the best approximation from this: http://java.sun.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html#getObjectSize(java.lang.Object)你可能会从中得到最好的近似值: http : //java.sun.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html#getObjectSize(java.lang.Object)

This article , and this comprehensive one demonstrates/details this approach这篇文章和这篇 综合文章演示/详细介绍了这种方法

The int[] or int[][] is not a primitive data type. int[]int[][]不是原始数据类型。 It is an Object in Java.它是 Java 中的一个对象。 And with an Object, the size cannot be calculated straight away.并且对于对象,无法立即计算大小。

I know this is an old question, but I had the same one and the information given in this thread did not help me.我知道这是一个老问题,但我有同样的问题,并且该线程中提供的信息对我没有帮助。 The source that gave me the information I needed: https://www.javamex.com/tutorials/memory/array_memory_usage.shtml给我所需信息的来源: https : //www.javamex.com/tutorials/memory/array_memory_usage.shtml

Here is my case: I have a big array这是我的情况:我有一个大数组

int a[][] = new int[m][n];

where "big" is in fact misleading: m is big (3^18 = 387420489) but n is small (4).其中“大”实际上是误导:m 大(3^18 = 387420489)但 n 小(4)。 I kept running into memory problems that I did not understand, since m * n * 4 = 6198727824 (~6GB) whereas I have 16GB of RAM (and 12 allowed to the JVM with -Xmx12G).我一直遇到我不明白的内存问题,因为 m * n * 4 = 6198727824 (~6GB) 而我有 16GB 的 RAM(和 12 个允许使用 -Xmx12G 的 JVM)。 The link I just put gave me the answer:我刚刚放的链接给了我答案:

each of the 10 rows has its own 12-byte object header, 4*10=40 bytes for the actual row of ints, and again, 4 bytes of padding to bring the total for that row to a multiple of 8 10 行中的每一行都有自己的 12 字节对象标头,4*10=40 字节用于实际的整数行,还有 4 字节的填充使该行的总数达到 8 的倍数

This is where the memory of my two-dimensional array substantially deviates from 4 * m * n: here, because n is small (4), the size of each row is really different from 4 * n;这就是我的二维数组的内存大幅偏离4*m*n的地方:这里,因为n很小(4),所以每一行的大小真的和4*n不一样; if you apply the formula given in the link (even if it is approximate), you get, for each row: 12 (header) + 4 * 4 (four ints) + 4 (padding to a multiple of 8 bytes) = 32. This is twice the cost I expected, and explains that I run into memory overflow.如果您应用链接中给出的公式(即使它是近似的),对于每一行,您会得到:12(标题)+ 4 * 4(四个整数)+ 4(填充到 8 个字节的倍数)= 32。这是我预期成本的两倍,并说明我遇到了内存溢出。

for original type:base type and size of Byte对于原始类型:基本类型和字节大小

  • boolean 1布尔值 1
  • byte 1字节 1
  • char 1字符 1
  • int 4整数 4
  • float 4浮动 4
  • long 8长8
  • double 8双8
  • Interger 24 (16 for Class instance + 4 for int + 4 for memory alignment)整数 24(16 用于类实例 + 4 用于 int + 4 用于内存对齐)

int a[M]: 24+4M int a[M]: 24+4M

(16 for Class + 4 for save array size + 4 for memory alignment) + (for M size of double, we need 4 * M) (Class 16 + 4 保存数组大小 + 4 内存对齐) + (M size of double, 我们需要 4 * M)

int a[M][N]: (24+4M) + M*(24+4N) = 24+28M+4MN ~~~4MN int a[M][N]: (24+4M) + M*(24+4N) = 24+28M+4MN ~~~4MN

treat a[M][N] as M size of double array a[N] plus one extra array to hold the reference of all M size array start point.将 a[M][N] 视为 M 大小的双数组 a[N] 加上一个额外的数组来保存所有 M 大小数组起点的引用。

Yann's answer above is correct, I double-checked it via a Heap dump. Yann 上面的回答是正确的,我通过堆转储对其进行了仔细检查。

Here's the data we need to compute the exact memory size of an array (source: https://www.javamex.com/tutorials/memory/array_memory_usage.shtml ) :这是我们计算数组的确切内存大小所需的数据(来源: https : //www.javamex.com/tutorials/memory/array_memory_usage.shtml ):

  • Java selected type size (eg: double = 8 bytes) 'S' Java 选定的类型大小(例如:double = 8 字节)'S'
  • Java array rounding up to multiple of: 8 bytes 'q' Java 数组四舍五入到以下各项的倍数:8 字节 'q'
  • Java reference size: 4 bytes 'R' Java 参考大小:4 字节 'R'
  • Java array header size: 12 bytes 'H' Java 数组头大小:12 字节 'H'

Forumulas:论坛:

For a double[N] = (N * S + H) + (N * S + H) % q = 'x'对于 double[N] = (N * S + H) + (N * S + H) % q = 'x'

For a double[M][N] = [M * (x + R) + H] + [M * (x + R) + H] % q = 'y'对于 double[M][N] = [M * (x + R) + H] + [M * (x + R) + H] % q = 'y'

As an example:举个例子:

double[10] = (10 * 8 + 12) + (10 * 8 + 12) % 8 = 96 Bytes double[10] = (10 * 8 + 12) + (10 * 8 + 12) % 8 = 96 字节

double[10][10] = [10 * (96 + 4) + 12] + [10 * (96 + 4) + 12] % 8 = 1016 Bytes double[10][10] = [10 * (96 + 4) + 12] + [10 * (96 + 4) + 12] % 8 = 1016 字节

Simply multiplying the underlying primitive type (wrong) would have yield:简单地乘以底层原始类型(错误)会产生:

double[10] = 8 * 10 = 80 Bytes double[10] = 8 * 10 = 80 字节

double[10][10] = 8 * 10 * 10 = 800 Bytes double[10][10] = 8 * 10 * 10 = 800 字节

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM