How to calculate the memory usage of a Java array

Following on from our discussion of the memory usage of Java objects, on this page, we consider the special case of arrays. Recall that:

(To query the memory usage of an array from within a Java program, you can use the memory utility class of the Classmexer agent available from this site.)

Memory usage of a single-dimension array

A single-dimension array is a single object. As expected, the array has the usual object header. However, this object head is 12 bytes to accommodate a four-byte array length. Then comes the actual array data which, as you might expect, consists of the number of elements multiplied by the number of bytes required for one element, depending on its type. The memory usage for one element is 4 bytes for an object reference; for a list of the memory usage of primitive types, see the page on Java data types. If the total memory usage of the array is not a multiple of 8 bytes, then the size is rounded up to the next mutlitple of 8 (just as for any other object).

Note that a boolean array requires one byte per element, even though each element actually only stores a single bit of useful information. (If you need to store a series of bits more compactly, see the BitSet class.)

Memory usage of a two-dimensional array

In a language such as C, a two-dimensional array (or indeed any multidimensional array) is essentially a one-dimensional array with judicious pointer manipulation. This is not the case in Java, where a multidimensional array is actually a set of nested arrays. This means that every row of a two-dimensional array has the overhead of an object, since it actually is a separate object!

For example, let's consider a 10x10 int array. Firstly, the "outer" array has its 12-byte object header followed by space for the 10 elements. Those elements are object references to the 10 arrays making up the rows. That comes to 12+4*10=52 bytes, which must then be rounded up to the next multiple of 8, giving 56. Then, 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. So in total, that gives 11*56=616 bytes. That's a bit bigger than if you'd just counted on 10*10*4=400 bytes for the hundred "raw" ints themselves.

Multidimensional arrays

For arrays of more than 2 dimensions, the above logic repeats: each row of the "outer" array is now an array of references to a further array, which contains the actual primitive data (or references if it is an object array).

If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.