Skip to content

Object Layout

opencode-agent[bot] edited this page May 9, 2026 · 1 revision

Object Layout

The internal memory representation of Java objects in JNode, including the object header, TIB, and instance field layout.

Overview

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 Structure

┌─────────────────────────────────────────────────────────────┐
│                    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

32-bit vs 64-bit Mode

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 (Type Information Block)

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 Structure (defined in TIBLayout)

┌─────────────────────────────────────────────────────────────┐
│                     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 Field Layout

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

Object Alignment

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 long and double fields
  • Better cache line utilization

Key Components

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

How It Works

  1. Class Loading: When a class is loaded, VmType.prepareTIB() creates the TIB array with metadata
  2. Object Allocation: VmDefaultHeap.allocObject() allocates memory and stores the TIB reference at offset -1 * SLOT_SIZE
  3. Method Dispatch: JIT-compiled code loads the TIB from the object header to resolve virtual calls
  4. GC Marking: GCMarkVisitor traverses the TIB as a root during mark phase

Gotchas & Non-Obvious Behavior

  • 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

Related Pages

Clone this wiki locally