Skip to content

Commit 524b0df

Browse files
committed
Mark static fields as reachabke
1 parent b14e4ea commit 524b0df

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

jvm/src/garbage_collector.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
1+
use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, vec::Vec};
22
use core::mem::forget;
33
use java_constants::FieldAccessFlags;
44

55
use bytemuck::cast_slice;
66
use hashbrown::{hash_set::Entry, HashMap, HashSet};
77
use parking_lot::Mutex;
88

9-
use crate::{thread::JvmThread, ClassInstance, JavaValue, Jvm};
9+
use crate::{class_loader::Class, thread::JvmThread, ClassInstance, JavaValue, Jvm};
1010

1111
// XXX java/util/Vector, java/util/HashMap internal..
1212
type RustVector = Arc<Mutex<Vec<Box<dyn ClassInstance>>>>;
@@ -16,12 +16,13 @@ pub fn determine_garbage(
1616
jvm: &Jvm,
1717
threads: &BTreeMap<u64, JvmThread>,
1818
all_class_instances: &HashSet<Box<dyn ClassInstance>>,
19-
classes: Vec<Box<dyn ClassInstance>>,
19+
classes: &BTreeMap<String, Class>,
2020
) -> Vec<Box<dyn ClassInstance>> {
2121
let mut reachable_objects = HashSet::new();
2222

23-
classes.into_iter().for_each(|x| {
24-
find_reachable_objects(jvm, &x, &mut reachable_objects);
23+
classes.values().for_each(|x| {
24+
find_reachable_objects(jvm, &x.java_class(), &mut reachable_objects);
25+
find_static_reachable_objects(jvm, x, &mut reachable_objects);
2526
});
2627

2728
threads
@@ -41,6 +42,37 @@ pub fn determine_garbage(
4142
all_class_instances.difference(&reachable_objects).cloned().collect()
4243
}
4344

45+
fn find_static_reachable_objects(jvm: &Jvm, class: &Class, reachable_objects: &mut HashSet<Box<dyn ClassInstance>>) {
46+
let fields = class.definition.fields();
47+
for field in fields {
48+
if !field.access_flags().contains(FieldAccessFlags::STATIC) {
49+
continue;
50+
}
51+
52+
let descriptor = field.descriptor();
53+
let value = class.definition.get_static_field(&*field).unwrap();
54+
55+
if descriptor.starts_with("L") && descriptor.ends_with(";") {
56+
if let JavaValue::Object(Some(value)) = value {
57+
find_reachable_objects(jvm, &value, reachable_objects);
58+
}
59+
} else if descriptor.starts_with("[") {
60+
if let JavaValue::Object(Some(value)) = value {
61+
reachable_objects.insert(value.clone());
62+
63+
let array = value.as_array_instance().unwrap();
64+
let values = array.load(0, array.length()).unwrap();
65+
66+
for value in values {
67+
if let JavaValue::Object(Some(value)) = value {
68+
find_reachable_objects(jvm, &value, reachable_objects);
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
75+
4476
#[allow(clippy::borrowed_box)]
4577
fn find_reachable_objects(jvm: &Jvm, object: &Box<dyn ClassInstance>, reachable_objects: &mut HashSet<Box<dyn ClassInstance>>) {
4678
let entry = reachable_objects.entry(object.clone());
@@ -64,17 +96,17 @@ fn find_reachable_objects(jvm: &Jvm, object: &Box<dyn ClassInstance>, reachable_
6496

6597
let fields = object.class_definition().fields();
6698
for field in fields {
99+
if field.access_flags().contains(FieldAccessFlags::STATIC) {
100+
continue;
101+
}
102+
67103
let descriptor = field.descriptor();
68104

69105
if !descriptor.starts_with("L") && !descriptor.starts_with("[") {
70106
continue;
71107
}
72108

73-
let value = if field.access_flags().contains(FieldAccessFlags::STATIC) {
74-
object.class_definition().get_static_field(&*field).unwrap()
75-
} else {
76-
object.get_field(&*field).unwrap()
77-
};
109+
let value = object.get_field(&*field).unwrap();
78110

79111
if descriptor.starts_with("L") && descriptor.ends_with(";") {
80112
if let JavaValue::Object(Some(value)) = value {

jvm/src/jvm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,9 +592,9 @@ impl Jvm {
592592
let garbage = {
593593
let threads = self.inner.threads.read();
594594
let all_objects = self.inner.all_objects.read();
595-
let classes = self.inner.classes.read().values().map(|x| x.java_class()).collect();
595+
let classes = self.inner.classes.read();
596596

597-
determine_garbage(self, &threads, &all_objects, classes)
597+
determine_garbage(self, &threads, &all_objects, &classes)
598598
};
599599

600600
let garbage_count = garbage.len();

0 commit comments

Comments
 (0)