jvm-rs/crates/core/src/objects/object_manager.rs
2025-12-29 06:51:03 +10:30

704 lines
18 KiB
Rust

use crate::class::RuntimeClass;
use crate::class_file::ClassFlags;
use crate::class_file::attributes::ArrayType;
use crate::error::VmError;
use crate::objects::array::{Array, ArrayReference};
use crate::objects::object::{
Object, ObjectReference, Reference, ReferenceKind, string_from_bytes,
};
use crate::value::Value;
use crate::{BaseType, ThreadId, VmSymbols};
use dashmap::DashMap;
use jni::sys::{jint, jlong};
use parking_lot::{Condvar, Mutex};
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
#[derive(Default)]
pub struct ObjectManager {
pub objects: HashMap<u32, ReferenceKind>,
strings: HashMap<String, u32>,
monitors: DashMap<u32, Arc<Monitor>>,
max_memory: usize,
next_id: AtomicU32,
}
impl ObjectManager {
pub fn max_memory(&self) -> usize {
self.max_memory
}
fn next_id(&self) -> u32 {
self.next_id.fetch_add(1, Ordering::Relaxed)
}
/// Returns the total bytes in use by all managed objects and arrays
pub fn bytes_in_use(&self) -> usize {
self.objects
.values()
.map(|kind| match kind {
ReferenceKind::ObjectReference(r) => {
let guard = r.lock();
guard
.fields
.iter()
.map(|entry| entry.value().size_bytes())
.sum()
}
ReferenceKind::ArrayReference(a) => a.size_bytes(),
})
.sum()
}
pub fn new_object(&mut self, class: Arc<RuntimeClass>) -> ObjectReference {
let id = self.next_id();
if self.objects.contains_key(&id) {
let next = self.next_id();
let key_pairs = self
.objects
.iter()
.map(|(id, obj)| format!("id: {id} obj: {}", obj.class().this_class))
.collect::<Vec<_>>();
eprintln!("next: {} all: \n{:#?}", next, key_pairs)
}
assert!(
!self.objects.contains_key(&id),
"Generated ID already exists!"
);
let object = Arc::new(Mutex::new(Object {
id,
class: class.clone(),
fields: Default::default(),
}));
self.objects.insert(id, ReferenceKind::from(object.clone()));
object
}
pub fn new_primitive_array(&mut self, class: Arc<RuntimeClass>, count: i32) -> ArrayReference {
let id = self.next_id();
assert!(
!self.objects.contains_key(&id),
"Generated ID already exists!"
);
let symbol = class
.this_class
.strip_prefix("[")
.unwrap()
.chars()
.next()
.unwrap();
let array_type = symbol.into();
let array_ref = match array_type {
BaseType::Int => {
ArrayReference::Int(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Byte => {
ArrayReference::Byte(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Short => {
ArrayReference::Short(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Long => {
ArrayReference::Long(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Float => {
ArrayReference::Float(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Double => {
ArrayReference::Double(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Char => {
ArrayReference::Char(Arc::new(Mutex::new(Array::new(id, class, count))))
}
BaseType::Boolean => {
ArrayReference::Boolean(Arc::new(Mutex::new(Array::new(id, class, count))))
}
};
self.objects
.insert(id, ReferenceKind::ArrayReference(array_ref.clone()));
array_ref
}
pub fn new_object_array(&mut self, class: Arc<RuntimeClass>, count: i32) -> ArrayReference {
let id = self.next_id();
assert!(
!self.objects.contains_key(&id),
"Generated ID already exists!"
);
let array_ref = ArrayReference::Object(Arc::new(Mutex::new(Array::new(id, class, count))));
self.objects
.insert(id, ReferenceKind::ArrayReference(array_ref.clone()));
array_ref
}
pub fn new_object_array_from(
&mut self,
class: Arc<RuntimeClass>,
values: Box<[Reference]>,
) -> ArrayReference {
let id = self.next_id();
assert!(
!self.objects.contains_key(&id),
"Generated ID already exists!"
);
let array_ref =
ArrayReference::Object(Arc::new(Mutex::new(Array::from((id, class, values)))));
self.objects
.insert(id, ReferenceKind::ArrayReference(array_ref.clone()));
array_ref
}
pub fn new_byte_array(
&mut self,
class: Arc<RuntimeClass>,
vector: Box<[i8]>,
) -> ArrayReference {
let id = self.next_id();
assert!(
!self.objects.contains_key(&id),
"Generated ID already exists!"
);
let array_ref =
ArrayReference::Byte(Arc::new(Mutex::new(Array::from((id, class, vector)))));
self.objects
.insert(id, ReferenceKind::ArrayReference(array_ref.clone()));
array_ref
}
pub fn get(&self, id: u32) -> ReferenceKind {
self.objects
.get(&id)
.unwrap_or_else(|| {
let objs = self
.objects
.iter()
.map(|(x, y)| format!("{x} : {y}"))
.collect::<Vec<_>>();
panic!("Object must be present id: {id}\n{objs:#?}")
})
.clone()
}
pub fn get_interned_string(&self, utf: &str) -> Option<ObjectReference> {
self.strings
.get(utf)
.and_then(|e| self.get(*e).try_into_object_reference().ok())
}
pub fn new_string(
&mut self,
byte_array_class: Arc<RuntimeClass>,
string_class: Arc<RuntimeClass>,
utf8: &str,
) -> ObjectReference {
let key = utf8.to_owned();
let jstr = self.new_object(string_class);
let byte_vec = utf8
.encode_utf16()
.flat_map(|e| e.to_le_bytes())
.map(|e| e as i8)
.collect::<Vec<_>>();
let barray = self.new_byte_array(byte_array_class, byte_vec.into_boxed_slice());
jstr.lock().fields.insert(
"value".to_string(),
Value::from(Some(ReferenceKind::ArrayReference(barray))),
);
jstr.lock()
.fields
.insert("coder".to_string(), Value::from(1i8));
jstr.lock()
.fields
.insert("hash".to_string(), Value::from(0i32));
jstr.lock()
.fields
.insert("hashIsZero".to_string(), Value::from(false));
let id = jstr.lock().id;
debug_assert!(!self.strings.contains_key(&key), "String already interned");
self.strings.insert(key, id);
jstr
}
pub fn intern_existing_string(&mut self, utf: String, obj_id: u32) -> u32 {
*self.strings.entry(utf).or_insert(obj_id)
}
pub fn new_class(
&mut self,
class_class: Arc<RuntimeClass>,
name: Reference,
module: Reference,
modifiers: ClassFlags,
primitive: bool,
component_type: Reference,
) -> ObjectReference {
let string = self
.transmute_string(name.clone().unwrap().try_into_object_reference().unwrap())
.unwrap();
if string.contains("byte") {
println!("!!!!!");
}
let module = None;
let modifiers = 17u16;
let class_redefined_count = 0i32;
let clazz = self.new_object(class_class);
{
let clakz = clazz.lock();
clakz.set_field("name", Value::from(name));
clakz.set_field("module", Value::from(module));
clakz.set_field("modifiers", Value::from(modifiers));
clakz.set_field("primitive", Value::from(primitive));
clakz.set_field("classRedefinedCount", Value::from(class_redefined_count));
clakz.set_field("componentType", Value::from(component_type))
}
clazz
}
/// using pure wizardry, transmute a string object into a rust string
pub fn transmute_string(&self, string: ObjectReference) -> Result<String, VmError> {
let guard = string.lock();
let value_field = guard
.fields
.get("value")
.ok_or_else(|| VmError::InvariantError("String must have value field".to_string()))?;
let array_ref = match *value_field {
Value::Reference(Some(ReferenceKind::ArrayReference(ref arr))) => arr.clone(),
_ => {
return Err(VmError::InvariantError(
"String value field must be a byte array".to_string(),
));
}
};
let bytes = match array_ref {
ArrayReference::Byte(byte_arr) => {
let arr_guard = byte_arr.lock();
arr_guard.backing.clone()
}
_ => {
return Err(VmError::InvariantError(
"String value must be a byte array".to_string(),
));
}
};
Ok(string_from_bytes(&bytes))
}
pub fn monitor_enter(&self, thread_id: ThreadId, obj_id: u32) {
let monitor = self
.monitors
.entry(obj_id)
.or_insert_with(|| Arc::new(Monitor::new()))
.clone();
// DashMap entry guard dropped here, map unlocked
let mut inner = monitor.inner.lock();
while inner.owner.is_some() && inner.owner != Some(thread_id) {
monitor.condvar.wait(&mut inner);
}
inner.owner = Some(thread_id);
inner.entry_count += 1;
}
pub fn monitor_exit(&self, thread_id: ThreadId, obj_id: u32) -> Result<(), VmError> {
let monitor = self
.monitors
.get(&obj_id)
.ok_or_else(|| VmError::InvariantError("Monitor not found for object".to_string()))?
.clone();
let mut inner = monitor.inner.lock();
if inner.owner != Some(thread_id) {
return Err(VmError::InvariantError(
"Thread does not own monitor".to_string(),
));
}
inner.entry_count -= 1;
if inner.entry_count == 0 {
inner.owner = None;
monitor.condvar.notify_one();
}
Ok(())
}
pub fn wait(
&self,
thread_id: ThreadId,
obj_id: u32,
timeout_millis: jlong,
) -> Result<(), VmError> {
let monitor = self
.monitors
.get(&obj_id)
.ok_or_else(|| VmError::InvariantError("Monitor not found".into()))?
.clone();
let mut inner = monitor.inner.lock();
if inner.owner != Some(thread_id) {
return Err(VmError::InvariantError(
"IllegalMonitorStateException".into(),
));
}
// Save entry count, release monitor
let saved_count = inner.entry_count;
inner.entry_count = 0;
inner.owner = None;
inner.wait_count += 1;
// Wake a thread waiting to enter
monitor.condvar.notify_one();
// Wait for notify
if timeout_millis > 0 {
monitor.wait_condvar.wait_for(
&mut inner,
std::time::Duration::from_millis(timeout_millis as u64),
);
} else {
monitor.wait_condvar.wait(&mut inner);
}
inner.wait_count -= 1;
// Reacquire monitor
while inner.owner.is_some() {
monitor.condvar.wait(&mut inner);
}
inner.owner = Some(thread_id);
inner.entry_count = saved_count;
Ok(())
}
pub fn notify_one(&self, obj_id: u32) {
if let Some(monitor) = self.monitors.get(&obj_id) {
monitor.wait_condvar.notify_one();
}
}
pub fn notify_all(&self, obj_id: u32) {
if let Some(monitor) = self.monitors.get(&obj_id) {
monitor.wait_condvar.notify_all();
}
}
pub fn clone_object(&mut self, source: &ReferenceKind) -> Result<ReferenceKind, VmError> {
match source {
ReferenceKind::ArrayReference(arr) => self.clone_array(arr),
ReferenceKind::ObjectReference(obj) => {
let class = obj.lock().class.clone();
if !class.implements(VmSymbols::CLONEABLE) {
return Err(VmError::InvariantError("CloneNotSupported".to_string()));
}
self.clone_instance(obj)
}
}
}
fn clone_array(&mut self, arr: &ArrayReference) -> Result<ReferenceKind, VmError> {
let new_arr = match arr {
ArrayReference::Int(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Int(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Byte(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Byte(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Short(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Short(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Long(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Long(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Float(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Float(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Double(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Double(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Char(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Char(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Boolean(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Boolean(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(),
})))
}
ArrayReference::Object(a) => {
let guard = a.lock();
let new_id = self.next_id();
ArrayReference::Object(Arc::new(Mutex::new(Array {
id: new_id,
class: guard.class.clone(),
backing: guard.backing.clone(), // shallow clone - copies references, not objects
})))
}
};
let id = new_arr.id();
self.objects
.insert(id, ReferenceKind::ArrayReference(new_arr.clone()));
Ok(ReferenceKind::ArrayReference(new_arr))
}
fn clone_instance(&mut self, obj: &ObjectReference) -> Result<ReferenceKind, VmError> {
let guard = obj.lock();
let class = guard.class.clone();
// Create a new object with the same class
let new_obj = self.new_object(class);
// Copy all fields (shallow copy)
{
let new_guard = new_obj.lock();
for entry in guard.fields.iter() {
new_guard
.fields
.insert(entry.key().clone(), entry.value().clone());
}
}
Ok(ReferenceKind::ObjectReference(new_obj))
}
}
pub struct Monitor {
inner: Mutex<MonitorInner>,
condvar: Condvar,
wait_condvar: Condvar,
}
struct MonitorInner {
owner: Option<ThreadId>,
entry_count: u32,
wait_count: u32,
}
impl Monitor {
fn new() -> Self {
Self {
inner: Mutex::new(MonitorInner {
owner: None,
entry_count: 0,
wait_count: 0,
}),
condvar: Condvar::new(),
wait_condvar: Condvar::new(),
}
}
}
//reflection
impl ObjectManager {
fn get_from_klass(&self, klass: Arc<RuntimeClass>) -> ReferenceKind {
self.get(klass.mirror())
}
pub fn new_constructor(
&mut self,
index: jint,
modifiers: jint,
parameters: Box<[Arc<RuntimeClass>]>,
exceptions: Box<[Arc<RuntimeClass>]>,
class_array_class: Arc<RuntimeClass>,
declaring_class: Arc<RuntimeClass>,
constructor_class: Arc<RuntimeClass>,
) -> ObjectReference {
let parameters = parameters
.iter()
.map(|c| {
let mirror_id = c.mirror.get().unwrap();
Some(self.get(*mirror_id))
})
.collect::<Box<[_]>>();
let exceptions = exceptions
.iter()
.map(|c| {
let mirror_id = c.mirror.get().unwrap();
Some(self.get(*mirror_id))
})
.collect::<Box<[_]>>();
let constructor_object = self.new_object(constructor_class);
let parameter_types = self.new_object_array_from(class_array_class.clone(), parameters);
let exception_types = self.new_object_array_from(class_array_class, exceptions);
let signature = Value::NULL;
let annotations = Value::NULL;
let parameter_annotations = Value::NULL;
{
let obj = constructor_object.lock();
obj.set_field("clazz", Value::from(self.get_from_klass(declaring_class)));
obj.set_field("slot", Value::from(index));
obj.set_field("parameterTypes", Value::from(parameter_types));
obj.set_field("exceptionTypes", Value::from(exception_types));
obj.set_field("modifiers", Value::from(modifiers));
obj.set_field("override", Value::from(false));
obj.set_field("signature", signature);
obj.set_field("annotations", annotations);
obj.set_field("parameterAnnotations", parameter_annotations);
}
constructor_object
}
pub fn new_thread_group(
&mut self,
thread_group_class: Arc<RuntimeClass>,
name: ObjectReference,
max_priority: jint,
) -> ObjectReference {
let tg_object = self.new_object(thread_group_class);
{
let obj = tg_object.lock();
obj.set_field("name", name.into());
obj.set_field("maxPriority", max_priority.into());
}
tg_object
}
pub fn new_holder(
&mut self,
holder_class: Arc<RuntimeClass>,
group: ObjectReference,
priority: jint,
status: jint,
) -> ObjectReference {
let holder_object = self.new_object(holder_class);
{
let obj = holder_object.lock();
obj.set_field("group", group.into());
obj.set_field("priority", priority.into());
obj.set_field("threadStatus", status.into());
}
holder_object
}
pub fn new_thread(
&mut self,
thread_class: Arc<RuntimeClass>,
eetop: jlong,
tid: jlong,
name: ObjectReference,
holder: ObjectReference,
) -> ObjectReference {
let tg_object = self.new_object(thread_class);
{
let obj = tg_object.lock();
obj.set_field("eetop", eetop.into());
obj.set_field("tid", tid.into());
obj.set_field("name", name.into());
obj.set_field("holder", holder.into());
}
tg_object
}
pub fn new_method_type(
&mut self,
method_type_class: Arc<RuntimeClass>,
class_array_class: Arc<RuntimeClass>,
rtype: ReferenceKind, // Class mirror for return type
ptypes: Vec<ReferenceKind>, // Class mirrors for param types
) -> ObjectReference {
let ptypes_array =
self.new_object_array_from(class_array_class, ptypes.into_iter().map(Some).collect());
let mt = self.new_object(method_type_class);
{
let obj = mt.lock();
obj.set_field("rtype", Value::from(Some(rtype)));
obj.set_field("ptypes", Value::from(ptypes_array));
}
mt
}
pub fn new_member_name(
&mut self,
member_name_class: Arc<RuntimeClass>,
clazz: ReferenceKind, // declaring class mirror
name: ObjectReference, // method/field name as String
method_type: ObjectReference,
flags: jint, // REF_invokeStatic, etc encoded
) -> ObjectReference {
let mn = self.new_object(member_name_class);
{
let obj = mn.lock();
obj.set_field("clazz", Value::from(Some(clazz)));
obj.set_field("name", Value::from(name));
obj.set_field("type", Value::from(method_type));
obj.set_field("flags", Value::from(flags));
}
mn
}
pub fn new_direct_method_handle(
&mut self,
dmh_class: Arc<RuntimeClass>,
member: ObjectReference,
method_type: ObjectReference,
) -> ObjectReference {
let mh = self.new_object(dmh_class);
{
let obj = mh.lock();
obj.set_field("type", Value::from(method_type));
obj.set_field("member", Value::from(member));
}
mh
}
}