<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[raycodes]]></title><description><![CDATA[Hi, I’m Ray (Reza) Shams, a software engineer passionate about backend development, cloud technologies, and open-source projects.]]></description><link>https://raycodes.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1758838688719/6019a752-7dd7-4bb4-b275-65a1cf97cb31.png</url><title>raycodes</title><link>https://raycodes.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 11:55:34 GMT</lastBuildDate><atom:link href="https://raycodes.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Java 25 - Compact Object Headers – How to Save Memory in Production]]></title><description><![CDATA[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, im...]]></description><link>https://raycodes.dev/java-25-compact-object-headers-how-to-save-memory-in-production</link><guid isPermaLink="true">https://raycodes.dev/java-25-compact-object-headers-how-to-save-memory-in-production</guid><category><![CDATA[Java]]></category><category><![CDATA[performance]]></category><category><![CDATA[object]]></category><dc:creator><![CDATA[Ray Shams]]></dc:creator><pubDate>Sun, 21 Sep 2025 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758750887883/96ba1095-7d57-4029-a07e-50bc6634e38c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Java 25</strong> is out, and it brings some exciting improvements under the hood. One of the most impactful features for backend developers is <strong>Compact Object Headers (JEP 519)</strong>.</p>
<p>Even if your code hasn’t changed, upgrading to Java 25 can <strong>reduce memory usage</strong>, <strong>improve CPU cache efficiency</strong>, and <strong>make garbage collection faster</strong>—all automatically.</p>
<p>In this post, we’ll dive deep into:</p>
<ul>
<li><p>What an <strong>object header</strong> is.</p>
</li>
<li><p>Why it matters for memory-heavy applications.</p>
</li>
<li><p>How <strong>Java 25’s compact headers</strong> reduce overhead.</p>
</li>
<li><p>Practical impact and examples.</p>
</li>
</ul>
<h2 id="heading-what-is-an-object-header">What is an Object Header?</h2>
<p>Every Java object has a <strong>small header</strong> that stores metadata required by the JVM:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Component</td><td>Purpose</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Mark Word</strong></td><td>Stores object state: hashcode, GC age, lock info</td></tr>
<tr>
<td><strong>Class Pointer</strong></td><td>Points to the class metadata (methods, type info)</td></tr>
<tr>
<td><strong>Array Length</strong></td><td>Only for arrays</td></tr>
</tbody>
</table>
</div><p>On a <strong>64-bit HotSpot JVM</strong>, a typical object header is <strong>12–16 bytes</strong>, sometimes <strong>larger than the actual object data</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span> </span>{
    <span class="hljs-keyword">int</span> x;
    <span class="hljs-keyword">int</span> y;
}
</code></pre>
<ul>
<li><p>Fields = 8 bytes (2 ints)</p>
</li>
<li><p>Header = 12 bytes → padded to 16 bytes</p>
</li>
<li><p><strong>Total object size ≈ 24 bytes</strong></p>
</li>
</ul>
<p>Even for tiny objects, the header overhead is significant when you create millions of instances.</p>
<h2 id="heading-why-java-25-compact-object-headers-matter">Why Java 25 Compact Object Headers Matter</h2>
<p>Java 25 introduces <strong>Compact Object Headers</strong> (JEP 519), which <strong>reduce the size of the object header</strong> by:</p>
<ul>
<li><p>Packing the <strong>Mark Word</strong> and <strong>Class pointer</strong> more efficiently</p>
</li>
<li><p>Eliminating unnecessary padding</p>
</li>
<li><p>Keeping <strong>all GC and lock functionality intact</strong></p>
</li>
</ul>
<p>This is completely <strong>transparent to developers</strong>—no code changes are required.</p>
<h2 id="heading-memory-layout-before-vs-after">Memory Layout – Before vs After</h2>
<h3 id="heading-before-java-25">Before Java 25</h3>
<pre><code class="lang-apache">┌───────────────┐
│ <span class="hljs-attribute">Mark</span> Word     │ --&gt; <span class="hljs-number">8</span>B
├───────────────┤
│ <span class="hljs-attribute">Class</span> Ptr     │ --&gt; <span class="hljs-number">4</span>B
│ <span class="hljs-attribute">Padding</span>       │ --&gt; <span class="hljs-number">4</span>B
└───────────────┘
[ <span class="hljs-attribute">Object</span> Fields ]
</code></pre>
<ul>
<li>Header = 12 bytes → padded to 16 bytes</li>
</ul>
<h3 id="heading-after-java-25-compact-headers">After Java 25 Compact Headers</h3>
<pre><code class="lang-plaintext">┌───────────────┐
│ Compact Header │  ← Mark + Class packed efficiently (~8B)
└───────────────┘
[ Object Fields ]
</code></pre>
<ul>
<li><p>Header = ~8 bytes</p>
</li>
<li><p>Memory savings: <strong>~50%</strong> for small objects</p>
</li>
</ul>
<hr />
<h2 id="heading-practical-example">Practical Example</h2>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Order</span> </span>{
    <span class="hljs-keyword">int</span> id;
    <span class="hljs-keyword">boolean</span> delivered;
}

List&lt;Order&gt; orders = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1_000_000</span>; i++) {
    orders.add(<span class="hljs-keyword">new</span> Order());
}
</code></pre>
<p><strong>Impact:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>JVM</td><td>Memory per object</td><td>Total memory for 1M objects</td></tr>
</thead>
<tbody>
<tr>
<td>Java 17</td><td>16 bytes</td><td>~16 MB</td></tr>
<tr>
<td>Java 25</td><td>~8 bytes</td><td>~8 MB</td></tr>
</tbody>
</table>
</div><p>Saving <strong>~8 MB per million objects</strong> just by upgrading the JVM.</p>
<h2 id="heading-how-to-enable-verify">How to Enable / Verify</h2>
<ul>
<li><p><strong>Enabled by default</strong> on <strong>64-bit HotSpot JVM</strong></p>
</li>
<li><p>JVM flags (optional):</p>
</li>
</ul>
<pre><code class="lang-bash"><span class="hljs-comment"># Enable compact headers</span>
-XX:+UseCompactObjectHeaders

<span class="hljs-comment"># Disable compact headers</span>
-XX:-UseCompactObjectHeaders
</code></pre>
<p>You can also use tools like <strong>JOL (Java Object Layout)</strong> to inspect the <strong>object size</strong>:</p>
<pre><code class="lang-java">System.out.println(GraphLayout.parseInstance(<span class="hljs-keyword">new</span> Order()).toPrintable());
</code></pre>
<hr />
<h2 id="heading-who-benefits-most">Who Benefits Most?</h2>
<ul>
<li><p><strong>Microservices</strong> creating millions of DTOs per second</p>
</li>
<li><p><strong>Kafka consumers</strong> buffering large numbers of small messages</p>
</li>
<li><p><strong>In-memory caches</strong> storing small objects like <code>Point</code>, <code>Order</code>, etc.</p>
</li>
<li><p><strong>High-throughput applications</strong> where GC and memory footprint matter</p>
</li>
</ul>
<p>Even a small reduction in object size <strong>scales up to huge savings</strong> in production environments.</p>
<h2 id="heading-highlights">Highlights</h2>
<ul>
<li><p><strong>Java 25 Compact Object Headers</strong> reduce per-object memory overhead on 64-bit JVMs.</p>
</li>
<li><p><strong>No code changes needed</strong>—simply upgrade to Java 25.</p>
</li>
<li><p>Can <strong>improve GC performance</strong>, memory usage, and CPU cache efficiency.</p>
</li>
<li><p>Ideal for <strong>high-performance, memory-sensitive applications</strong>.</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>