Search code examples
javaarraysjvmjvm-hotspot

How to calculate Java array's memory size?


I know how to calculate a Java object's memory size by adding three parts: header + properties + reference.

I also know that a Java array is an object too.

But when I read "Understanding the JVM advanced Features and Best Practices, second Edition", it says Java array's header consists of three parts; mark word, class pointer and array length.

It will always be 24 bytes in Hotspot 64-bits JVM.

But in a 32-bit JVM, how can I calculate a Java array's memory size?

I hope you guys can give me some example Java code to show me how to calculate an object's memory size not, limited to array object.


Solution

  • The actual object size is implementation specific and there is not even a requirement that the needed size for an object stays the same during its lifetime.

    There’s an article on wiki.openjdk.java.net stating:

    Object header layout

    An object header consists of a native-sized mark word, a klass word, a 32-bit length word (if the object is an array), a 32-bit gap (if required by alignment rules), and then zero or more instance fields, array elements, or metadata fields. (Interesting Trivia: Klass metaobjects contain a C++ vtable immediately after the klass word.)

    The gap field, if it exists, is often available to store instance fields.

    If UseCompressedOops is false (and always on ILP32 systems), the mark and klass are both native machine words. For arrays, the gap is always present on LP64 systems, and only on arrays with 64-bit elements on ILP32 systems.

    If UseCompressedOops is true, the klass is 32 bits. Non-arrays have a gap field immediately after the klass, while arrays store the length field immediately after the klass.

    You calculation “header + properties + reference” for an object’s size is not correct. First, references to an object are not part of the referent’s object size. There can be an arbitrary numbers of references to the same object, but these references don’t have to be in the heap memory or in RAM at all, as optimized code may access an object purely via CPU registers.

    Further, as hinted in the quote above, there are alignment rules which make the calculation of the memory required for the fields nontrivial. There might be a gap in the header which might be used for storing instance fields, if there are fields of a type fitting into it. While the fields of the same class may get arranged to minimize the padding, a subclass has to live with the superclass’ layout, potentially adding more fields to it and may only fill in the gaps if it has fields of fitting types, otherwise, there might be even more gaps due to the class hierarchy.

    For arrays, you can derive from the quoted article that the 32 bit HotSpot representation uses a header of 12 bytes, unless the type is long[] or double[], in which case it will be 16 bytes.

    For the 64 bit implementation, the UseCompressedOops option (which is on by default), allows to combine a 64 bit mark word with a 32 bit klass and 32 bit length, to a header of 16 bytes total. Only if UseCompressedOops is off, the header will be 24 bytes.