2025-12-29 06:51:03 +10:30

134 lines
3.4 KiB
Rust

use crate::{get_thread, resolve_object};
use jni::sys::{JNI_FALSE, JNI_TRUE, jboolean, jclass, jobject};
use jni::sys::{JNIEnv, jint};
use jni::sys::{jobjectArray, jstring};
use log::trace;
use roast_vm_core::FieldType;
use roast_vm_core::objects::ReferenceKind;
use std::ptr;
#[unsafe(no_mangle)]
pub unsafe extern "system" fn Java_java_lang_Class_getPrimitiveClass<'local>(
env: *mut JNIEnv,
_class: jclass,
name: jstring,
) -> jclass {
let thread = &*get_thread(env);
let rust_string = {
let obj_id = name as u32;
let obj_ref = match thread.gc.read().get(obj_id) {
ReferenceKind::ObjectReference(obj) => obj,
_ => return 0 as jclass,
};
thread.gc.write().transmute_string(obj_ref).unwrap()
};
let klass = thread.get_class(&rust_string).unwrap();
let class = thread.gc.read().get(*klass.mirror.wait());
class.id() as jclass
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn Java_java_lang_Class_forName0(
env: *mut JNIEnv,
_class: jclass,
name: jstring,
initialize: jboolean,
_loader: jobject,
_caller: jclass,
) -> jclass {
trace!("Java_java_lang_Class_forName0");
let thread = &*get_thread(env);
// Convert java.lang.String to Rust string
let string_obj = resolve_object(thread, name).unwrap();
let class_name = thread.gc.read().transmute_string(string_obj).unwrap();
// Convert "java.lang.String" -> "java/lang/String"
let class_name = class_name.replace('.', "/");
// Load the class
let rtc = match thread.get_class(&class_name) {
Ok(c) => c,
Err(_) => {
// TODO: throw ClassNotFoundException
return ptr::null_mut();
}
};
if initialize == JNI_TRUE {
thread.ensure_initialised(&rtc).unwrap();
}
// Return the mirror
*rtc.mirror.get().unwrap() as jclass
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn Java_java_lang_Class_getDeclaredConstructors0(
env: *mut JNIEnv,
class: jobject,
public_only: jboolean,
) -> jobjectArray {
let thread = &*get_thread(env);
let klass = thread
.loader
.lock()
.class_from_mirror_id(class as u32)
.unwrap();
let only_public = public_only == 1u8;
let constructors = klass
.methods
.iter()
.filter(|e| e.name == "<init>" && (!only_public || e.flags.ACC_PUBLIC))
.enumerate()
.map(|(idx, constructor)| {
let modifiers: u16 = constructor.flags.clone().into();
let parameters = constructor
.desc
.parameters
.iter()
.map(|x| thread.get_class(&x.as_class_name()).unwrap())
.collect::<Vec<_>>()
.into_boxed_slice();
let exceptions = Vec::new().into_boxed_slice();
let class_array_class = thread.get_class("[Ljava/lang/Class;").unwrap();
let declaring_class = thread.get_class(&constructor.class).unwrap();
let constructor_class = thread.get_class("java/lang/reflect/Constructor").unwrap();
let con = thread.gc.write().new_constructor(
idx as jint,
modifiers as jint,
parameters,
exceptions,
class_array_class,
declaring_class,
constructor_class,
);
Some(ReferenceKind::from(con))
})
.collect::<Vec<_>>();
let constructor_array_class = thread
.get_class("[Ljava/lang/reflect/Constructor;")
.unwrap();
let output = thread
.gc
.write()
.new_object_array_from(constructor_array_class, constructors.into_boxed_slice());
output.id() as jobjectArray
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn Java_java_lang_Class_desiredAssertionStatus0(
_env: *mut JNIEnv,
_class: jclass,
_this: jclass,
) -> jboolean {
JNI_FALSE
}