Compact object headers

Java 25 Course · lesson 6 of 16 · 4 min read

A JVM change that shrinks every object on the heap, with no code change at all.

Open this lesson in the learning hub

Key points

  • Every Java object carries a header: a mark word plus a class pointer, 12 bytes before your fields.
  • JEP 519 compresses that to 8 bytes on 64-bit platforms and makes it final in 25.
  • For heaps full of small objects the saving is real - often several percent of live heap.
  • Smaller objects mean better cache behaviour and less GC pressure, not just a smaller number.
  • It is a runtime flag, not a source change: nothing in your code needs to know.

Example

import java.lang.management.ManagementFactory;

public class Main {
    record Point(int x, int y) { }        // two ints + header

    public static void main(String[] args) {
        Runtime rt = Runtime.getRuntime();
        System.gc();
        long before = rt.totalMemory() - rt.freeMemory();

        Point[] points = new Point[500_000];
        for (int i = 0; i < points.length; i++) {
            points[i] = new Point(i, i * 2);
        }

        long after = rt.totalMemory() - rt.freeMemory();
        long bytesEach = (after - before) / points.length;

        System.out.println("objects allocated : " + points.length);
        System.out.println("approx bytes each : " + bytesEach + "  (header + 2 ints + padding)");
        System.out.println("header is 12 bytes on this JVM; Java 25 compacts it to 8");
        System.out.println("saving across 500k objects: ~" + (points.length * 4 / 1024) + " KB");
        System.out.println("JVM: " + ManagementFactory.getRuntimeMXBean().getVmVersion());
    }
}

Compact object headers give a heap saving for free - the win scales with how many small objects you make.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Java 25 Course course, and every lesson in it is listed on the Java 25 Course contents page.