JVM: The first 4 buleans are optimized, not 5

I am currently profiling some Java applications using the Eclipse Memory Analyzer plugin (using the standard hprof jconsole dump), and I noticed some strange results on the size of the computed object:

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 boolean elements are somehow filled in the object header, how is it?

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

+4
source share
3 answers

Inside 64-bit JVM HotSpot with CompressedOops

  • Object header consists of 8 bytes markWord+ 4 bytes instanceKlasslink
  • boolean 1
  • 8

  • align8(8 + 4) = 16 bytes
  • 4 align8(8 + 4 + 4*1) = 16 bytes
  • 5 align8(8 + 4 + 5*1) = align8(17) = 24 bytes
+2

; 8 12 ( OOPS /). , , 8 ( ).

, 12- ; 4 - obbject. ; 17 (12 + 5 ), 8, 24 .

+5

I do not understand who you are. Using 1.8, from Netbeans:

public static class C1 {
    boolean a,b,c,d;
}
public static class C2 {
    boolean a,b,c,d,e;
}
public static void main(String[] args) {
    try {
           Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor();
           unsafeConstructor.setAccessible(true);
           Unsafe unsafe = unsafeConstructor.newInstance();
           String[] fieldNames = new String[] {"a","b","c","d"};
           for (String fieldName : fieldNames) {
           System.out.println(fieldName+": "+unsafe.objectFieldOffset(C1.class.getDeclaredField(fieldName)));
        }
    }
    catch(Exception e) {
       e.printStackTrace();
    }
 }

gives the result

a: 12
b: 13
c: 14
d: 15

... which indicates that each Boolean value occupies a separate byte offset in the object. The header is 12 bytes.

+1
source

All Articles