# 3. Compact object headers are the default (JEP 534) Prev: [2. G1](02-g1-default.md) · Next: [4. Post-quantum TLS](04-post-quantum-tls.md) Every Java object starts with a header. On JDK 26 with default settings it is **12 bytes** (8 bytes mark word plus a 4-byte compressed class pointer). With compact object headers the two are squeezed into **8 bytes**. JEP 534 makes that the default in 27; `-XX:-UseCompactObjectHeaders` turns it off. ## Measured with JOL [`scripts/object-headers.sh`](../scripts/object-headers.sh) downloads JOL 0.17 (sha1-checked) and runs [`HeaderDemo`](../object-headers/src/HeaderDemo.java) three ways. The summary is [15](output/15-headers-summary.txt); raw runs are [10](output/10-headers-jdk26.txt) (26), [11](output/11-headers-jdk27.txt) (27), [12](output/12-headers-jdk27-opt-out.txt) (27 with the opt-out, which reproduces 26 exactly). | Object | JDK 26 | JDK 27 | |---|---|---| | `Object` | 16 B | 8 B | | `Point { int x; int y; }` | 24 B | 16 B | | `Order { long id; int quantity; boolean paid; String customer; }` | 32 B | 32 B | | boxed `Long` | 24 B | 16 B | | boxed `Integer` | 16 B | 16 B | | `int[3]` | 32 B | 24 B | | 1,000,000 boxed `Long` in an `ArrayList` | 28.9 MB | 20.9 MB | | 1,000,000 `Point` in an `ArrayList` | 28.9 MB | 20.9 MB | | 1,000,000 boxed `Integer` in an `ArrayList` | 20.9 MB | 20.9 MB | The pattern to notice: saving 4 bytes only helps when it crosses an 8-byte alignment boundary. `Order` and boxed `Integer` do not move, because padding was already absorbing the difference. Your heap will not shrink by "4 bytes times object count"; it shrinks by the number of objects that were sitting just past a boundary. ## Two things that bite * **JOL 0.17 cannot inspect a `record`.** `Unsafe.objectFieldOffset` refuses records ([13](output/13-jol-record-failure.txt)). The workaround `-Djol.magicFieldOffset=true` prints a layout but shows the header mark as `N/A` ([14](output/14-jol-record-workaround.txt)). * **Anything that hard-codes 12 bytes** (off-heap size estimators, "object overhead" constants in capacity plans, tests that assert `Instance size`) is now wrong by default. `-XX:+UseCompressedClassPointers` is also no longer an option in 27: the JVM prints "Ignoring option UseCompressedClassPointers; support was removed in 27.0" ([60](output/60-removed-options.txt)). Prev: [2. G1](02-g1-default.md) · Next: [4. Post-quantum TLS](04-post-quantum-tls.md)