-
Notifications
You must be signed in to change notification settings - Fork 0
Object Layout
The internal memory representation of Java objects in JNode, including the object header, TIB, and instance field layout.
Every Java object in JNode consists of a fixed-size header followed by instance fields. The header contains metadata the VM needs for type resolution, garbage collection, and method dispatch. Understanding this layout is essential for debugging GC issues, writing native code that manipulates objects, and understanding JIT compiler output.
┌─────────────────────────────────────────────────────────────┐
│ OBJECT HEADER │
├─────────────────────┬───────────────────────────────────────┤
│ Flags (1 slot) │ TIB (1 slot) │
│ @ offset -2 │ @ offset -1 │
└─────────────────────┴───────────────────────────────────────┘
│ │
▼ ▼
-2 * SLOT_SIZE -1 * SLOT_SIZE
│ │
▼ ▼
[object start] ──────► Instance Fields Start at Offset 0
The header consists of exactly 2 slots (defined in ObjectLayout.HEADER_SLOTS):
| Slot | Name | Purpose |
|---|---|---|
-2 |
FLAGS_SLOT | Runtime flags (interruptibility, finalizeable, etc.) |
-1 |
TIB_SLOT | Reference to the Type Information Block |
The slot size depends on the architecture word size:
| Mode | SLOT_SIZE | Header Size |
|---|---|---|
| 32-bit | 4 bytes | 8 bytes |
| 64-bit | 8 bytes | 16 bytes |
The offsets are defined as negative indices in ObjectLayout.java because they extend before the object's memory address. The actual object data begins at offset 0.
The TIB is a reference to an Object[] array that contains type metadata. It is created during class loading in VmType.prepareTIB() and stored in VmClassType.tib.
┌─────────────────────────────────────────────────────────────┐
│ TIB Array │
├─────────┬─────────┬─────────────┬─────────────┬────────────┤
│ Index 0 │ Index 1 │ Index 2 │ Index 3 │ Index 4 │
├─────────┼─────────┼─────────────┼─────────────┼────────────┤
│ VmType │ IMT │ IMT Collisions │ Compiled │ Superclass │
│ │ │ (boolean[]) │ IMT │ array │
└─────────┴─────────┴─────────────┴─────────────┴────────────┘
VMTYPE_INDEX IMT_INDEX IMTCOLLISIONS COMPILED_IMT SUPERCLASSES
INDEX _INDEX _INDEX _INDEX
| Index | Field | Type | Purpose |
|---|---|---|---|
| 0 | VMTYPE_INDEX | VmType |
The VmType instance for this class |
| 1 | IMT_INDEX | Object[] |
Interface Method Table for interface method dispatch |
| 2 | IMTCOLLISIONS_INDEX | boolean[] |
Tracks hash collisions in IMT |
| 3 | COMPILED_IMT_INDEX | Object |
Architecture-specific compiled method table |
| 4 | SUPERCLASSES_INDEX | VmType[] |
Array of superclasses for method resolution |
| 5+ | FIRST_METHOD_INDEX | — | Virtual method table (method pointers) |
The JIT compilers use the TIB to:
- Resolve method targets for virtual calls
- Check object types during type checks
- Traverse class hierarchy for GC root marking
Instance fields begin immediately after the header at offset 0. Field layout is computed by VmType.layoutInstanceFields() during class loading. Fields are laid out in declaration order, with alignment applied per-field based on type:
- Reference fields: 4 bytes (32-bit) or 8 bytes (64-bit)
-
Primitive fields:
boolean/byte= 1,short/char= 2,int/float= 4,long/double= 8
All objects are aligned to 8 bytes (ObjectLayout.OBJECT_ALIGN). This is enforced by ObjectLayout.objectAlign():
public static int objectAlign(int value) {
return (value + OBJECT_ALIGN - 1) & ~(OBJECT_ALIGN - 1);
}This alignment ensures:
- Efficient access to fields of all sizes
- Proper handling of
longanddoublefields - Better cache line utilization
| Class / File | Role |
|---|---|
core/src/core/org/jnode/vm/classmgr/ObjectLayout.java |
Defines header offsets, slot indices, alignment constants |
core/src/core/org/jnode/vm/classmgr/TIBLayout.java |
TIB array index constants |
core/src/core/org/jnode/vm/classmgr/VmType.java |
Creates and manages TIB during class loading |
core/src/core/org/jnode/vm/classmgr/VmClassType.java |
Stores the TIB reference (getTIB()) |
core/src/core/org/jnode/vm/memmgr/def/VmDefaultHeap.java |
Uses TIB offset for object allocation |
-
Class Loading: When a class is loaded,
VmType.prepareTIB()creates the TIB array with metadata -
Object Allocation:
VmDefaultHeap.allocObject()allocates memory and stores the TIB reference at offset-1 * SLOT_SIZE - Method Dispatch: JIT-compiled code loads the TIB from the object header to resolve virtual calls
-
GC Marking:
GCMarkVisitortraverses the TIB as a root during mark phase
-
Negative offsets: The header extends before the object address, so TIB is at
objectRef - SLOT_SIZE - Interface vs Class: Only class instances have a full TIB. Array types have a minimal TIB. Interface types don't have a TIB at all
- TIB is shared: All instances of the same class share one TIB object
- Header size varies: The header is always 2 slots, but slot size differs between 32/64-bit
- Alignment affects heap: The 8-byte alignment applies to the final object size, not just fields
- Memory-Management — GC interaction with object headers
- JIT-Compilers — How compilers use the TIB for method dispatch
-
VM-Magic —
VmMagic.getTIB()and other unsafe operations - Architecture — Overview of the VM layer