jvm-rs/docs/object-management.md

3.5 KiB

Object Management

Location: crates/core/src/objects/

Object Representation

Java objects are represented through a multi-layered abstraction:

pub struct Object {
    pub id: u32,                           // Unique identifier
    pub class: Arc<RuntimeClass>,          // Runtime class reference
    pub fields: DashMap<String, Value>,    // Concurrent field storage
}

pub type ObjectReference = Arc<Mutex<Object>>;
  • Objects: Contain a unique ID (u32), runtime class reference, and field storage (DashMap)
  • ObjectReference: Arc<Mutex<Object>> - reference-counted, thread-safe smart pointer
  • Value wrapper: The Value enum encapsulates both primitives and references for operand stack/local variable storage

Array Management

Arrays are type-safe with separate variants for primitives and objects:

pub enum ArrayReference {
    Int(Arc<Mutex<Array<jint>>>),
    Byte(Arc<Mutex<Array<jbyte>>>),
    Short(Arc<Mutex<Array<jshort>>>),
    Long(Arc<Mutex<Array<jlong>>>),
    Float(Arc<Mutex<Array<jfloat>>>),
    Double(Arc<Mutex<Array<jdouble>>>),
    Char(Arc<Mutex<Array<jchar>>>),
    Boolean(Arc<Mutex<Array<jboolean>>>),
    Object(Arc<Mutex<Array<Option<ReferenceKind>>>>),
}
  • Primitive arrays: Int, Byte, Short, Long, Float, Double, Char, Boolean
  • Object arrays: Can hold references to other objects
  • Array structure: Each array wraps a boxed slice Box<[T]> with id, class, and backing storage
  • Thread-safe: All arrays use Arc<Mutex<Array<T>>> for concurrent access

Allocation Strategy

Allocation is centralized in ObjectManager:

  • Object allocation: new_object() generates unique IDs via atomic counter and stores references in HashMap
  • Array allocation: Separate methods for primitive arrays (new_primitive_array()) and object arrays (new_object_array())
  • String interning: new_string() creates UTF-16 encoded strings with automatic interning via string pool
  • Memory tracking: bytes_in_use() calculates total heap usage across all objects/arrays

All allocated objects are registered in objects: HashMap<u32, ReferenceKind> for global access.

Reference Handling

Two-level reference system:

  1. ReferenceKind enum: Distinguishes between ObjectReference and ArrayReference
  2. Reference type alias: Option<ReferenceKind> (None = null)
  3. Conversion methods: Safe conversions with try_into_object_reference() and try_into_array_reference()

Memory Management

No explicit garbage collection - relies on Rust's reference counting:

  • Arc ensures objects live as long as references exist
  • Mutex provides thread-safe field/element access
  • Shallow cloning for clone() operations (copies references, not objects)
  • Array copy operations handle both primitive and object types with bounds checking

Object Synchronization

Monitor-based concurrency for synchronized operations:

pub struct Monitor {
    owner: Option<ThreadId>,
    entry_count: u32,
    condition: Condvar,
    mutex: Mutex<()>,
}
  • Operations: monitor_enter(), monitor_exit(), wait(), notify_one(), notify_all()
  • Wait semantics: Full support for Java-style wait/notify with timeout
  • Reentrant: Same thread can enter multiple times (tracked by entry_count)

Special Features

  • String handling: UTF-16 LE encoding with automatic String object creation
  • Reflection support: Methods to create Constructor, Method, MethodHandle objects
  • Class mirrors: Every class has an associated mirror object (java/lang/Class)