If I have:
int c[] = new int[10];
and
int a[][] = new int[2][3];
and in generally
an n*m*..*j
array
how can I calculate the real memory usage considering also the references variables?
-
2Is there a motivation behind getting the "real memory usage" of those arrays?bakkal– bakkal2010年06月04日 08:53:40 +00:00Commented Jun 4, 2010 at 8:53
7 Answers 7
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];
According to the 64-bit memory model, an int is 4 bytes, so all the elements will be 4*N bytes in size. In addition to that, Java has a 24 bytes array overhead and there's also 8 bytes for the actual array object. So that's a total of 32 + 4 * N bytes.
For a 2 dimensional array: 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.
It's true that a generalization for D dimensions is pretty complicated, but you get the idea.
-
Where do you get the 24 byte overhead from? I assume the number is for some specific VM.Jørgen Fogh– Jørgen Fogh2013年07月19日 11:01:50 +00:00Commented Jul 19, 2013 at 11:01
-
This was the answer I needed. I'm working on a project where I am going to need a pretty big array, I don't want to break it up into a bunch of disk operations and I need to know the how much memory these objects will consume. Thank you.Tucker Downs– Tucker Downs2014年08月12日 15:52:01 +00:00Commented Aug 12, 2014 at 15:52
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. 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.
-
2This answer is correct. There's always overhead due to type/GC information and whatnot. Plus there's the fact that Java doesn't have a true multidimensional array, only jagged arrays, which end up generating quite a bit of that overhead.Matti Virkkunen– Matti Virkkunen2010年06月04日 08:44:46 +00:00Commented Jun 4, 2010 at 8:44
-
how is represented in memory a multidimensional array?xdevel2000– xdevel20002010年06月04日 08:47:57 +00:00Commented Jun 4, 2010 at 8:47
-
I deleted my answer since I know of no way to calculate the exact size inclusive of overhead.bakkal– bakkal2010年06月04日 08:48:06 +00:00Commented Jun 4, 2010 at 8:48
-
5@xdevel2000: Java does not have multidimensional arrays. Only arrays of arrays.Matti Virkkunen– Matti Virkkunen2010年06月04日 08:51:55 +00:00Commented Jun 4, 2010 at 8:51
-
1@Matti Virkkunen: True. The VM still keeps track of how many layers of arrays are nested, so you can't assign an array of chars to an array of arrays of chars.Jørgen Fogh– Jørgen Fogh2010年06月04日 09:56:13 +00:00Commented Jun 4, 2010 at 9:56
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)
This article, and this comprehensive one demonstrates/details this approach
The int[]
or int[][]
is not a primitive data type. It is an Object in Java. And with an Object, the size cannot be calculated straight away.
-
where does
+sizeof(int)
come from?bakkal– bakkal2010年06月04日 08:42:44 +00:00Commented Jun 4, 2010 at 8:42 -
A reference might not be 4 bytes depending on your platform.Matti Virkkunen– Matti Virkkunen2010年06月04日 08:48:22 +00:00Commented Jun 4, 2010 at 8:48
-
@Matti: Agreed. The whole stuff is not correct. Let me edit it.bragboy– bragboy2010年06月04日 08:49:24 +00:00Commented Jun 4, 2010 at 8:49
-
Writing the reference memory as
sizeof(int)
is misleading, even if on that particular platform it is 4 bytes.bakkal– bakkal2010年06月04日 08:50:33 +00:00Commented Jun 4, 2010 at 8:50 -
I think if we keep on editing to make it technically correct we will settle with "there is no easy accurate way" :Pbakkal– bakkal2010年06月04日 08:52:05 +00:00Commented Jun 4, 2010 at 8:52
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
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). 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). 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
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; 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.
Yann's answer above is correct, I double-checked it via a Heap dump.
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) :
- Java selected type size (eg: double = 8 bytes) 'S'
- Java array rounding up to multiple of: 8 bytes 'q'
- Java reference size: 4 bytes 'R'
- Java array header size: 12 bytes 'H'
Forumulas:
For a 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'
As an example:
double[10] = (10 * 8 + 12) + (10 * 8 + 12) % 8 = 96 Bytes
double[10][10] = [10 * (96 + 4) + 12] + [10 * (96 + 4) + 12] % 8 = 1016 Bytes
Simply multiplying the underlying primitive type (wrong) would have yield:
double[10] = 8 * 10 = 80 Bytes
double[10][10] = 8 * 10 * 10 = 800 Bytes
for original type:base type and size of Byte
- boolean 1
- byte 1
- char 1
- int 4
- float 4
- long 8
- double 8
- Interger 24 (16 for Class instance + 4 for int + 4 for memory alignment)
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)
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.
-
when you are discussing different types, we may have different size, but for int, we could have an calculation(there may some gap due to memory alignment)Chuanzhou Tang– Chuanzhou Tang2017年02月22日 14:35:30 +00:00Commented Feb 22, 2017 at 14:35
-
M = ?
, the array is always declaredint
... this answer could be improved.solidsnack– solidsnack2017年07月26日 02:39:51 +00:00Commented Jul 26, 2017 at 2:39