# Java 25 - Compact Object Headers – How to Save Memory in Production

**Java 25** is out, and it brings some exciting improvements under the hood. One of the most impactful features for backend developers is **Compact Object Headers (JEP 519)**.

Even if your code hasn’t changed, upgrading to Java 25 can **reduce memory usage**, **improve CPU cache efficiency**, and **make garbage collection faster**—all automatically.

In this post, we’ll dive deep into:

* What an **object header** is.
    
* Why it matters for memory-heavy applications.
    
* How **Java 25’s compact headers** reduce overhead.
    
* Practical impact and examples.
    

## What is an Object Header?

Every Java object has a **small header** that stores metadata required by the JVM:

| Component | Purpose |
| --- | --- |
| **Mark Word** | Stores object state: hashcode, GC age, lock info |
| **Class Pointer** | Points to the class metadata (methods, type info) |
| **Array Length** | Only for arrays |

On a **64-bit HotSpot JVM**, a typical object header is **12–16 bytes**, sometimes **larger than the actual object data**.

**Example:**

```java
class Point {
    int x;
    int y;
}
```

* Fields = 8 bytes (2 ints)
    
* Header = 12 bytes → padded to 16 bytes
    
* **Total object size ≈ 24 bytes**
    

Even for tiny objects, the header overhead is significant when you create millions of instances.

## Why Java 25 Compact Object Headers Matter

Java 25 introduces **Compact Object Headers** (JEP 519), which **reduce the size of the object header** by:

* Packing the **Mark Word** and **Class pointer** more efficiently
    
* Eliminating unnecessary padding
    
* Keeping **all GC and lock functionality intact**
    

This is completely **transparent to developers**—no code changes are required.

## Memory Layout – Before vs After

### Before Java 25

```apache
┌───────────────┐
│ Mark Word     │ --> 8B
├───────────────┤
│ Class Ptr     │ --> 4B
│ Padding       │ --> 4B
└───────────────┘
[ Object Fields ]
```

* Header = 12 bytes → padded to 16 bytes
    

### After Java 25 Compact Headers

```plaintext
┌───────────────┐
│ Compact Header │  ← Mark + Class packed efficiently (~8B)
└───────────────┘
[ Object Fields ]
```

* Header = ~8 bytes
    
* Memory savings: **~50%** for small objects
    

---

## Practical Example

```java
class Order {
    int id;
    boolean delivered;
}

List<Order> orders = new ArrayList<>();
for (int i = 0; i < 1_000_000; i++) {
    orders.add(new Order());
}
```

**Impact:**

| JVM | Memory per object | Total memory for 1M objects |
| --- | --- | --- |
| Java 17 | 16 bytes | ~16 MB |
| Java 25 | ~8 bytes | ~8 MB |

Saving **~8 MB per million objects** just by upgrading the JVM.

## How to Enable / Verify

* **Enabled by default** on **64-bit HotSpot JVM**
    
* JVM flags (optional):
    

```bash
# Enable compact headers
-XX:+UseCompactObjectHeaders

# Disable compact headers
-XX:-UseCompactObjectHeaders
```

You can also use tools like **JOL (Java Object Layout)** to inspect the **object size**:

```java
System.out.println(GraphLayout.parseInstance(new Order()).toPrintable());
```

---

## Who Benefits Most?

* **Microservices** creating millions of DTOs per second
    
* **Kafka consumers** buffering large numbers of small messages
    
* **In-memory caches** storing small objects like `Point`, `Order`, etc.
    
* **High-throughput applications** where GC and memory footprint matter
    

Even a small reduction in object size **scales up to huge savings** in production environments.

## Highlights

* **Java 25 Compact Object Headers** reduce per-object memory overhead on 64-bit JVMs.
    
* **No code changes needed**—simply upgrade to Java 25.
    
* Can **improve GC performance**, memory usage, and CPU cache efficiency.
    
* Ideal for **high-performance, memory-sensitive applications**.
