How Much Memory Would Your Class Save as a Value Class?
Describe your class fields. See the current object layout (header, fields, padding) next to the projected Valhalla value class layout, with the byte savings calculated.
How JavaObjectLayoutCalc works
- 1
Define your class fields
Add fields one at a time by choosing a Java primitive type (int, long, double, etc.) or "Object ref" for reference fields. Or pick a preset to start with a common class shape.
- 2
Current layout is calculated
The tool applies documented HotSpot JVM layout rules: a 12-byte object header (8-byte mark word + 4-byte compressed class pointer), your field sizes, and alignment padding to the nearest 8-byte boundary.
- 3
Valhalla projection is generated
The scalarized layout strips the object header and padding. What remains is the raw sum of your field bytes plus a 1-byte null flag (since value classes in JDK 28 are still nullable).
- 4
Per-instance savings are shown
A visual bar chart compares the two layouts side by side, with the percentage reduction calculated.
- 5
Array projection scales the comparison
The slider shows what happens at 10, 1,000, 100,000, and 1,000,000 instances. Under the current model, each array element is an 8-byte pointer to a separately allocated object. With heap flattening, elements are stored inline with no pointers.
What the results mean
Header (blue)
The 12-byte object header every Java object carries: 8 bytes for the mark word (locking, GC age, identity hash) and 4 bytes for the compressed class pointer. This is the overhead Valhalla eliminates entirely.
Fields (green)
The actual data your class stores. This is the only part that survives scalarization. The size depends on your field types: a byte is 1 byte, an int is 4, a long is 8, and an object reference is 4 (compressed oops).
Padding (gray)
HotSpot aligns every object to an 8-byte boundary. If your header + fields don't land on a multiple of 8, the JVM adds padding bytes. For example, a class with one byte field uses 12 (header) + 1 (field) = 13 bytes, padded to 16.
Null flag (amber)
Value classes in the JDK 28 preview are still nullable. The scalarized representation adds a 1-byte flag to track whether the value is null. This will disappear for null restricted types in a future JEP.
Savings percentage
The percentage reduction from the current layout to the scalarized layout. For small classes, this is typically 50 to 80%. The savings compound further in arrays because heap flattening also eliminates the 8-byte pointer per element.
HotSpot object layout reference
| Component | Size (bytes) | Notes |
|---|---|---|
| Mark word | 8 | GC age, lock state, identity hash |
| Class pointer | 4 (compressed) | 8 bytes if heap > 32 GB |
| byte / boolean | 1 | |
| short / char | 2 | |
| int / float | 4 | |
| long / double | 8 | |
| Object reference | 4 (compressed) | 8 bytes if heap > 32 GB |
| Alignment | to 8-byte boundary | Total size rounded up |
When to use this tool
| Scenario | What to enter | What to look for |
|---|---|---|
| Hot-loop data class | The primitive fields of your class (e.g. 2 ints for a Point) | Per-instance savings. If the class is used in tight loops, even small savings compound. |
| Large in-memory dataset | Fields of one element, then slide array size to your dataset scale | Total array savings. For million-element arrays, pointer overhead alone can cost 8 MB. |
| Evaluating Valhalla migration candidates | Each candidate class one at a time | Compare savings percentages. Classes with small fields and large array usage benefit most. |
| Teaching JVM internals | Simple classes (one field, then add more) | Watch how the header dominates small objects and how padding changes with different field combinations. |
| Deciding between refactoring to primitives or waiting for Valhalla | Your current class fields | The byte-level cost of the current object model, so you can weigh "refactor now" vs "wait for value classes." |
Important caveats
- Best case, not guaranteed. The scalarized layout shown is the theoretical best case. Scalarization requires the JIT compiler to prove the concrete type at the call site. When your value class is stored in an Object variable or an erased generic (like List<MyValue>), the JIT cannot scalarize it and falls back to the regular object layout.
- Field reordering not modeled. HotSpot may reorder fields internally to minimize padding (e.g., grouping 8-byte fields before 4-byte fields). This calculator uses declared order. The total size is usually the same, but field offsets may differ from JOL's runtime output.
- Compressed oops assumed. This calculator assumes compressed ordinary object pointers (oops), the default for heaps under 32 GB. If your heap exceeds 32 GB, object references are 8 bytes and the class pointer in the header is also 8 bytes.
- JDK 28 preview status. Value classes are a preview feature in JDK 28, disabled by default. The syntax and behavior can change in future releases. Do not migrate production code based on these projections until the feature exits preview.
Frequently Asked Questions
How much memory does a Java object header take?
On a 64-bit HotSpot JVM with compressed oops (the default for heaps under 32 GB), every object has a 12-byte header: an 8-byte mark word (used for locking, GC, and identity hash code) plus a 4-byte compressed class pointer.
Without compressed oops (heaps over 32 GB), the class pointer expands to 8 bytes, making the header 16 bytes total. This calculator uses the 12-byte compressed oops default.
How much memory would a value class save?
It depends on the class. The savings come from two places: eliminating the object header (12 bytes per instance) and removing alignment padding. For small classes like a Point with two int fields, the reduction is from 24 bytes (header + fields + padding) to 9 bytes (fields + null flag), a 62% saving per instance.
The savings compound dramatically in arrays. A million-element Point[] under the current model costs roughly 32 MB (pointers + objects). The same array with flattened value classes costs about 9 MB, a 72% reduction.
What is scalarization in Project Valhalla?
Scalarization is a JIT compiler optimization where a value object is broken down into its individual fields at the machine code level, rather than being passed as a pointer to a heap-allocated object. Instead of allocating a Color object with three byte fields and passing a pointer to it, the JIT passes the three bytes (plus a null flag) directly as register values or stack slots.
This eliminates allocation entirely for that instance. No heap memory is used, no garbage collection is needed. The catch: scalarization only works when the JIT can prove the concrete type at the call site. It typically fails when the static type is a supertype like Object or an erased generic type parameter.
How do I calculate Java object size?
The formula for HotSpot (64-bit, compressed oops) is:
Total = alignUp(header + sum_of_field_sizes, 8)
header = 12 bytes (8 mark + 4 compressed class ptr)
byte/boolean = 1 byte
short/char = 2 bytes
int/float = 4 bytes
long/double = 8 bytes
reference = 4 bytes (compressed oops)
alignment = round up to nearest 8-byte boundaryFor authoritative runtime measurement, use the Java Object Layout (JOL) library: org.openjdk.jol:jol-core. JOL reads the actual VM layout at runtime, including any reordering the JVM applies. This calculator uses the documented default rules, which match JOL's output for standard HotSpot configurations.
How does this compare to the Java Object Layout (JOL) library?
| JavaObjectLayoutCalc | JOL (jol-core) | |
|---|---|---|
| Runs in | Browser, no install | JVM, add as dependency |
| Measures | Calculated from documented rules | Actual VM layout at runtime |
| Valhalla comparison | Yes, side-by-side | No |
| Array projection | Yes, with slider | Manual code needed |
| Field reordering | No (uses declared order) | Yes (shows actual VM order) |
| Best for | Quick estimates, learning | Production profiling |
Use this calculator for quick what-if exploration and Valhalla projections. Use JOL when you need exact runtime measurements for a specific JVM version and configuration.
Can value classes be null in JDK 28?
Yes. Value classes in the JDK 28 preview are still reference types. They have given up object identity but remain nullable. This is why the scalarized representation in this calculator includes a 1-byte null flag. Non nullable (null restricted) types are a separate, later JEP. See our Project Valhalla in JDK 28 article for the full explanation of why this surprises most developers.
Is my data sent to any server?
No. All calculations run entirely in your browser using basic arithmetic on documented JVM constants. No data is sent anywhere, no cookies are set, and the tool works offline once the page has loaded.