1- use alloc:: { boxed:: Box , collections:: BTreeMap , sync:: Arc , vec:: Vec } ;
1+ use alloc:: { boxed:: Box , collections:: BTreeMap , string :: String , sync:: Arc , vec:: Vec } ;
22use core:: mem:: forget;
33use java_constants:: FieldAccessFlags ;
44
55use bytemuck:: cast_slice;
66use hashbrown:: { hash_set:: Entry , HashMap , HashSet } ;
77use 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..
1212type 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) ]
4577fn 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 {
0 commit comments