125 lines
3.8 KiB
Markdown
125 lines
3.8 KiB
Markdown
# 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<RwLock<Vec<(String, Library)>>>`.
|
|
|
|
## 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<String, *const c_void>`
|
|
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<Arg>
|
|
```
|
|
|
|
- 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::<ReturnType>(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 |