22

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?

xdevel2000
  • 20,780
  • 41
  • 129
  • 196

7 Answers7

24

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 Jul 19 '13 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 Aug 12 '14 at 15:52
18

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.

Community
  • 1
  • 1
Jørgen Fogh
  • 7,516
  • 2
  • 36
  • 46
  • 2
    This 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 Jun 04 '10 at 08:44
  • how is represented in memory a multidimensional array? – xdevel2000 Jun 04 '10 at 08:47
  • I deleted my answer since I know of no way to calculate the *exact* size inclusive of overhead. – bakkal Jun 04 '10 at 08:48
  • 5
    @xdevel2000: Java does not have multidimensional arrays. Only arrays of arrays. – Matti Virkkunen Jun 04 '10 at 08: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 Jun 04 '10 at 09:56
3

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

Ryan Fernandes
  • 8,238
  • 7
  • 36
  • 53
2

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.

bragboy
  • 34,892
  • 30
  • 114
  • 171
2

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
  • 31
  • 2
1

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

GennaroC
  • 31
  • 2
0

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 Feb 22 '17 at 14:35
  • `M = ?`, the array is always declared `int`... this answer could be improved. – solidsnack Jul 26 '17 at 02:39