javajvmintegerobject-layoutjol

java.lang.Integer object layout and it's overhead


I used a tool called JOL (Java Object Layout) which tries to analyze object layout. It comes with a cli and I used it to analyze java.lang.Integer. I see that Integer object is taking 12 extra bytes for overhead. That overhead can be 4 bytes for the address of class that object belongs to, another 4 for garbage collection, but what about the remaining 4 bytes? I know that objects have an integer hashCode value but I don't think it is unique (i.e. it does not use the location of memory, it uses the primitive value instead) because:

Integer a = new Integer(12);
Integer b = new Integer(12);

System.out.println(a.hashCode() == 12 && b.hashCode() == 12);
// prints: true

Log:

$ java -jar jol-cli/target/jol-cli.jar internals java.lang.Integer
# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 0-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

Instantiated the sample instance via public java.lang.Integer(int)
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           88 26 cf 22 (10001000 00100110 11001111 00100010) (584001160)
     12     4    int Integer.value                             0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

Solution

  • ... but what about the remaining 4 bytes?

    A missing 4 bytes would be padding to the next 8 byte boundary. Java heap nodes are a multiple of 8 bytes in size.


    But since this is a 64 bit JVM, the mark word is 8 bytes rather than 4 bytes, making 12 bytes of header overhead in total.