Java 25 Performance: How Compact Object Headers Save 20% Memory
Let's be real for a second: Java objects have always been a little... heavy.
For as long as most of us have been coding, every object in the HotSpot VM has carried a hidden "tax"—the object header. On 64-bit systems, this header takes up anywhere from 96 to 128 bits (that's 12 to 16 bytes!) just to exist.
If you're creating millions of tiny objects—like Integer, Optional, or simple data carriers—you're often paying more for the packaging than the actual product.
But here's the good news: Java 25 is finally fixing this with JEP 519: Compact Object Headers. It's a feature that shrinks that overhead down to a lean 64 bits (8 bytes), and honestly, it's going to be a massive win for modern applications.
What is the 12-byte object header tax in Java?
So, what exactly was taking up all that space? Before Java 25, an object header had two main roommates:
- Mark Word (64 bits): This holds the messy stuff like hash codes, GC age, and locking info.
- Class Word (64 bits): A pointer telling the JVM, "Hey, I'm a String" or "I'm a HashMap."
Even with optimizations like Compressed Oops, this usually rounded up to 16 bytes because of memory alignment rules.
Legacy Object Layout (16 bytes):
+------------------+------------------+
| Mark Word | Class Word |
| (8 bytes) | (4 bytes) |
+------------------+------------------+
| Padding | Fields |
| (4 bytes) | ... |
+------------------+------------------+Think about it: if you have 10 million Integer objects in memory, you aren't just storing numbers. You're storing 160MB of headers. That adds up fast.
How does JEP 519 reduce object header size?
The Java team basically pulled a "compression" magic trick with JEP 519. They asked, "Do we really need a separate field just to point to the class?"
The answer? Nope.
They figured out how to squash that class pointer inside the Mark Word itself. It's some serious bit-packing wizardry, but the result is a sleek, single 64-bit header.
Compact Object Header (8 bytes):
+---------------------------------------------------------------+
| Mark Word (64 bits) |
+---------------------------------------------------------------+
| 22 bits: Compressed Class ID | 31 bits: Hash | 4 bits: GC Age | ...
+---------------------------------------------------------------+- Compressed Class Pointer: Instead of a full address, it uses a 22-bit ID. This supports up to ~4 million classes, which is plenty for 99.9% of us.
- Everything Else: Hash codes and GC info are still there, safe and sound.
How much memory can compact object headers save?
Okay, cool tech, but what does it mean for your app?
It means free memory. By shaving 8 bytes off every single object, your heap usage drops like a rock.
- Small Objects: An
Integergoes from 16 bytes to 8 bytes. That's a 50% reduction in overhead. - Real-World Results: Amazon ran this on thousands of production services and saw an average heap reduction of 20%.
[!IMPORTANT] Less memory usage isn't just about saving RAM. It makes your Garbage Collector's life way easier. Less data to scan means faster GC cycles and less latency for your users.
How do you enable compact object headers in Java 25?
In Java 25, this feature is ready for prime time, but you have to ask for it (for now). Just add this flag:
java -XX:+UseCompactObjectHeaders -jar my-app.jarQuick note: If you were playing with this in Java 24, you needed the UnlockExperimentalVMOptions flag. You can drop that now—it's graduated!
What are the limitations of compact object headers?
While this is safe for almost everyone, there are two tiny edge cases:
- The "Mega-Monolith": If your app loads more than 4 million unique classes (which is... a lot), the compressed ID might run out of space.
- Heavy Locking: If you're doing a ton of synchronization on millions of objects at once, the JVM has a bit less room to track that, so it might need to do some extra work.
Final Thoughts
Compact Object Headers is one of those rare "free lunches" in software engineering. You don't have to rewrite your code, you don't have to refactor your architecture, and you get double-digit memory savings.
If you're upgrading to Java 25, flipping this switch should be the first thing you do. Your servers will thank you!
References
- JEP 519: Compact Object Headers — The official JDK Enhancement Proposal
- JOL (Java Object Layout) Tool — Tool for analyzing Java object memory layout
- OpenJDK Project Lilliput — The umbrella project for object header reduction
Keep Reading
- Mastering Virtual Threads in Java 25 — The other headline feature in Java 25 that transforms concurrency performance.
- Top Java Interview Questions for 2025 — Compact Object Headers and JVM internals are increasingly popular interview topics.
- 10 Essential Java Libraries Beyond Lombok — More tools to reduce boilerplate and boost productivity alongside JVM-level improvements.