Aleksey Shipilёv, @shipilev, aleksey@shipilev.net
This is an updated version of the Russian post I had roughly one year ago, way before Java Object Layout was available under OpenJDK, and the draft I had on GitHub was in infancy. The rationale for this post is to give the "runtime guy" perspective on every single blog post about Java object sizes and layouts.
Part I. Myths
Myth 0. You can figure out the object size once and for all
In reality, it depends on number of things. Target VM: what exactly you are running with? HotSpot? JRockit? J9? ahem Dalvik? Platform bitness: reference sizes are probably different, or even the basic types take a different number of bytes. Potential and actual optimizations, a la object inlining, scalarized fields, paddings, etc.
Myth 1. It is enough to sum up the field sizes to get the instance size
In reality, VMs are free to choose the representation for the basic types. Moreover, VMs are even forced to widen the representation beyond necessary for values domain in order to maintain basic language semantics (e.g. read/write atomicity) or to fit the underlying hardware requirements (e.g. always do aligned accesses). Moreover, the objects themselves also need to be aligned to maintain the field alignments intact. And then there are object headers…
Myth 2. It is enough to sum up the field sizes, PLUS the well-known header size
In reality, this data has questionable "shelf life", because VMs are free to choose the object representations, including the headers format. For example, current HotSpot can have the header sizes from 8 to 16 bytes in different conditions. JRockit will mostly have 8 bytes headers. That will change once HotSpot adopts the same object header format (that requires significant rework in locking schematics though).
Myth 3. Any sensible tool will show up correct instance size
In reality, it depends. HPROF will dump the instance size as calculated in Myth 1. That means, every single tool using HPROF (e.g. jhat, Eclipse MAT, VisualVM, Yourkit) as the source data is doomed to under/overestimate instance sizes, because they are forced to guess.
The moral here: we need online tools, which will give the instance size info on the spot.
Part II. Reality
The significant trouble for offline tools is HPROF format itself. HPROF is so "VM agnostic" that you don’t even know if you have been running 32- or 64-bit VM (yeah, there is "ID size", but is it really the reference size?). Good luck knowing if compressed references enabled or not. Forget about field layouts info, and object headers either, this info is completely lost. You only have the bitscale of instance field data with the class data describing what particular bits mean there. Hence, tools parsing HPROF need to guess the runtime layout of the objects.
Offline tools shootout
Let’s illustrate this last point. Make up some class, have a single instance of it, do the heapdump, and open the dump in various tools. Here’s our specimen for today:
public class Main {
private static Object obj;
public static void main(String[] args) throws Exception {
obj = new D();
System.in.read();
}
static class A {
long a;
}
static class B extends A {
boolean b;
}
static class C extends B {
int c;
}
static class D extends C {
boolean d;
}
}
Now, we can get a few heap dumps in various modes. For the sake of completeness, here is the exact environment the data is gathered. For today’s experiment, I downloaded the latest and greatest revisions of the tools available, as well as some of the recent JDKs:
Linux x86_64, 3.12+
HotSpot 24.0-b56, JDK 7u40
JRockit R28.2.5-20-152429-1.6.0_37-20120927-1915-linux-*, JDK 6u37
Visual VM 1.3.6
Eclipse Memory Analyzer Tool 1.3.0.20130517
YourKit Profiler 2013 (build 13066), evaluation license
This is what we get: