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 == "" && (!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::>() .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::>(); 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 }