Why Does JVM Allocate Objects in Multiple Steps? Explore Creation & Memory Layout
This article explains the JVM's object creation process—including stack allocation, TLAB checks, Eden and Survivor spaces, and GC handling—and details the memory layout of Java objects, covering object headers, class pointers, array lengths, padding, and the effect of compressed oops on 32‑bit versus 64‑bit systems.
Object Creation Process
Based on the HotSpot VM generational model, the following diagram illustrates the complete object creation flow.
A new object is allocated; first check if the thread stack can accommodate it.
If yes, allocation occurs directly on the stack.
If not, proceed to the next step.
Determine whether the object is large enough.
If large, it is placed directly into the old generation.
If not, continue to the next step.
Check whether the thread's TLAB (Thread‑Local Allocation Buffer) has sufficient space.
If sufficient, allocate in the TLAB.
If insufficient, move to other space in the Eden region and continue.
GC clearance.
If the object is reclaimed by GC, the process ends.
If not, proceed to the next step.
The object enters Survivor 1 and its age is evaluated.
If the age is large enough, it moves to the old region.
If not, it moves to Survivor 2 and the cycle repeats.
These steps explain why the JVM handles object creation with many conditional paths.
Why allocate on the stack first? The stack is thread‑private, allowing immediate deallocation via pop and simplifying cleanup when the thread terminates.
Why do large objects go directly to the old generation? Large objects require contiguous memory; placing them in the old generation avoids premature GC pressure.
Why use TLAB first? TLAB prevents multiple threads from contending for the same memory region, reducing allocation contention.
Why are there two Survivor spaces? Objects that survive a GC cycle are promoted from one Survivor space to the other, enabling whole‑space reclamation and improving efficiency.
Object Memory Layout
The following diagram shows the memory layout of a Java object (non‑array and array cases).
Object Header
The header consists of MarkWord and Class Pointer, plus Length for arrays.
MarkWord : stores lock bits, GC flags, etc.; 4 bytes on 32‑bit, 8 bytes on 64‑bit JVMs.
ClassPointer : points to the object's class metadata; 4 bytes on 32‑bit, 8 bytes on 64‑bit.
Length : present only in array objects to record array length; occupies 4 bytes.
Interface Data
Contains the actual instance fields; size depends on the fields' types (static fields are stored in the method area, not here).
Padding
Java objects are aligned to 8‑byte boundaries; padding bytes are added to ensure the total size is a multiple of 8.
Compressed Oops
The JVM option -XX:+UseCompressedOops compresses object references on 64‑bit JVMs, effectively halving pointer size and reducing the memory footprint of class pointers.
How many bytes does Object o = new Object() occupy?
Depending on whether compressed oops are enabled:
With compressed oops : MarkWord 8 bytes + ClassPointer 4 bytes + no instance data = 12 bytes; padding adds 4 bytes → total 16 bytes.
Without compressed oops : MarkWord 8 bytes + ClassPointer 8 bytes = 16 bytes (already 8‑byte aligned).
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
