# Native Methods and FFI System **Location**: `crates/core/src/thread.rs`, `crates/core/src/native/` ## Library Loading Native libraries are loaded dynamically using `libloading`: - **Location**: `crates/core/src/main.rs` - **Supported platforms**: Windows (.dll), Linux (.so) - **Libraries loaded**: - `roast_vm` - VM-specific native methods - `jvm` - Java virtual machine standard library - `java` - Java standard library Libraries are registered with the VM via `Vm::load_native_library()` and stored in `native_libraries: Arc>>`. ## Native Method Registration Native methods are registered through JNI's `RegisterNatives` function: - **Location**: `crates/core/src/native/jni.rs` - **Process**: 1. Java code calls `RegisterNatives()` with method names, signatures, and function pointers 2. VM generates JNI-formatted symbol names using `generate_jni_method_name()` 3. Function pointers are stored in `Vm::native_methods: DashMap` 4. Filters prevent registration of certain methods (e.g., Thread operations) ## Native Method Dispatch When a native method is invoked: - **Detection**: `MethodData::ACC_NATIVE` flag identifies native methods - **Location**: `crates/core/src/thread.rs` - **Flow**: 1. `execute_method()` checks if method has `ACC_NATIVE` flag 2. If static, adds class reference to args; otherwise adds instance reference 3. Calls `invoke_native()` with method reference and arguments ## FFI System - libffi Integration libffi is used to call native functions with correct calling conventions: ### Call Interface Building ```rust fn build_cif(&self) -> Cif { let mut args = vec![ Type::pointer(), // JNIEnv* Type::pointer(), // jclass/jobject ]; for v in self.desc.parameters { args.push(v.into()) } let return_type = ...; Builder::new().args(args).res(return_type).into_cif() } ``` - Constructs a Call Interface (Cif) from method signature - Maps Java types to FFI types - Always adds JNIEnv* and jclass/jobject as first two parameters ### Argument Marshalling ```rust fn build_args(params, storage, jnienv) -> Vec ``` - Marshals Java values to native format - Converts references to object IDs (u32) - Boxes primitives for FFI passing - Stores all values in a temporary vector ### Function Invocation ```rust let cp = CodePtr::from_ptr(p); cif.call::(cp, built_args.as_ref()); ``` - Converts function pointer to CodePtr - Calls through libffi with correct return type handling ## Type Mapping | Java Type | FFI Type | |-----------|----------| | byte | i8 | | char | u16 | | short | i16 | | int | i32 | | long | i64 | | float | f32 | | double | f64 | | boolean | i8 | | Object/Array | pointer | ## JNI Function Table A complete JNI function table is created and passed to native code: - **Location**: `crates/core/src/native/jni.rs` - **Implementation**: - 250+ JNI functions defined as unsafe extern "system" functions - Covers class operations, method invocation, field access, array operations, string handling - Many functions are stubs returning `todo!()` for unimplemented features ## Unsafe Support (sun.misc.Unsafe) Low-level unsafe operations are tracked: - **Location**: `crates/core/src/native/unsafe.rs` - **Features**: - Field offset registry mapping to class/field pairs - Off-heap memory allocation tracking - Base offset constant: `0x1_0000_0000` ## Key Implementation Characteristics - **Thread-safe**: All structures use `DashMap`, `RwLock`, or `Mutex` - **JNI environment**: Created per-thread, stored in `VmThread::jni_env` - **Symbol lookup**: Two-pass search (without params, then with params) - **Error handling**: Returns `VmError::NativeError` if symbols not found - **Tracking**: Maintains statistics on library resolution counts