I've searched about the size of a java object for a long time, there are a lot of answers like this, everyone is telling me that the size of the overhead of a java object, and how to calculate out the actual size. But how do they know that? I did not find any evidence from the official oracle documents. What is the evidence for that conclusion? Or the data was just come from some guesses based on some experiments?
Another thing. It is mentioned in the official document that there is a 'approximative' way to measure the object - the Instrumentation way, can anybody explain to me what is the 'approximately' means? When it is accurate, when it is not. Better to have the evidence.
For me the best method is the most down-to-earth one, using
memTaken()
;memTaken()
from the remembered one.There may be some transient allocation in the process, so you also need to run the GC. There are no guarantees provided by
System.gc()
, but this approach has always worked for me:You must be careful to ensure this gives stable results. For example, an approach is to calculate memory load for several different object counts and compare results. They should all match on the memory/instance answer they give.
I have advised this before, been put down for the lame solution, been recommended to use proper tooling, etc. So I used tooling, for example
jvisualvm
—and it gave wrong results. This method has never given wrong results to me.from experience.
Its up to the JVM. For OpenJDK based JVMs, 32-bit JVM has a different header size to 64-bit JVM as the header contains a reference. Other JVMs could be different again.
Essentially, yes.
When you measure the size of an object it can means many different things
Given you can have many difference answers depending on what you need to know, it is useful to have one number which is approximately close to all of these which you use for calculations.
Where you get a problem using Runtime is that the TLAB allocated data in large blocks. These large blocks can be further allocated in a multi-thread way. The downside is you don't get accurate memory used information.
run without options
Turn off the TLAB and you see with
-XX:-UseTLAB
This is much higher than you might expect because the class itself had to be loaded. If you create one instance of a Float first by adding to the start
you get
there are two different sizes for java objects: the shallow size and the retained size. the shallow size of an object is the sum of sizes of all it's fields: straight-forward for primitive members, and the size of a pointer for every non-primitive member(and this varies between 32 & 64 bit architectures). you can find the shallow size of an object at runtime using instrumantation. here is a nice tutorial
retained size is defined by the heap space that will be freed when the object is garbaged. finding the retained size of an object is not trivial, mainly because objects are usually composed of other objects. for example:
what is the retained size of a? and b? use a profiler to compute retained size (most profilers are using static heap analysis for that).
I think the answer can only be empirical as it is implementation dependent: