134 lines
3.4 KiB
Rust
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
|
|
}
|