Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JVM first 4 booleans optimized, not 5th

I'm currently profiling some Java application using the Eclipse Memory Analyzer plugin (using a standard jconsole hprof dump), and I noticed some strange results on computed object size:

private static class B1 extends B {
} // 16 bytes

private static class B2 extends B {
    boolean d1;
    boolean d2;
    boolean d3;
    boolean d4;
} // also 16 bytes!

private static class B3 extends B {
    boolean d1;
    boolean d2;
    boolean d3;
    boolean d4;
    boolean d5;
} // 24 bytes

Apparently the first 4 booleans are somehow stuffed away in the object header, how is this?

Note: Tested with Oracle JDK1.7 and JDK1.8, 64 bits, running on Linux x64.

like image 591
Laurent Grégoire Avatar asked Jan 10 '23 20:01

Laurent Grégoire


2 Answers

There is no optimization going on; the object header is commonly 8 or 12 bytes large, depending on VM and mode (Compressed OOPS on/off). Also commonly the memory granularity is 8 bytes (Object sizes in memory must always be a multiple of the granularity).

Your results clearly indicate that your VM uses a 12 byte header; so there is room for 4 bytes due to granularity without growing the obbject memory footprint. The booleans are commonly represented as bytes; so adding a 5th in your case requires 17 bytes (12 header + 5 bytes) rounded to next granularity 8 boundary gives 24 bytes.

like image 96
Durandal Avatar answered Jan 17 '23 17:01

Durandal


Within 64-bit HotSpot JVM with CompressedOops

  • Object header consists of 8 byte markWord + 4 byte instanceKlass reference
  • boolean field occupy 1 byte
  • Objects are 8-byte aligned

That is

  • an empty object occupies align8(8 + 4) = 16 bytes
  • an object with 4 boolean fields occupy align8(8 + 4 + 4*1) = 16 bytes
  • an object with 5 boolean fields occupy align8(8 + 4 + 5*1) = align8(17) = 24 bytes
like image 41
apangin Avatar answered Jan 17 '23 16:01

apangin