1010using System . Reflection ;
1111using System . Runtime . CompilerServices ;
1212using System . Runtime . InteropServices ;
13+ using System . Runtime . InteropServices . Java ;
1314using System . Threading ;
1415using Android . Runtime ;
1516using Java . Interop ;
@@ -20,7 +21,7 @@ class ManagedValueManager : JniRuntime.JniValueManager
2021{
2122 const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes . PublicConstructors | DynamicallyAccessedMemberTypes . NonPublicConstructors ;
2223
23- Dictionary < int , List < IJavaPeerable > > ? RegisteredInstances = new Dictionary < int , List < IJavaPeerable > > ( ) ;
24+ Dictionary < int , List < GCHandle > > ? RegisteredInstances = new ( ) ;
2425
2526 internal ManagedValueManager ( )
2627 {
@@ -35,7 +36,7 @@ public override void CollectPeers ()
3536 if ( RegisteredInstances == null )
3637 throw new ObjectDisposedException ( nameof ( ManagedValueManager ) ) ;
3738
38- var peers = new List < IJavaPeerable > ( ) ;
39+ var peers = new List < GCHandle > ( ) ;
3940
4041 lock ( RegisteredInstances ) {
4142 foreach ( var ps in RegisteredInstances . Values ) {
@@ -48,7 +49,8 @@ public override void CollectPeers ()
4849 List < Exception > ? exceptions = null ;
4950 foreach ( var peer in peers ) {
5051 try {
51- peer . Dispose ( ) ;
52+ if ( peer . Target is IDisposable disposable )
53+ disposable . Dispose ( ) ;
5254 }
5355 catch ( Exception e ) {
5456 exceptions = exceptions ?? new List < Exception > ( ) ;
@@ -74,33 +76,35 @@ public override void AddPeer (IJavaPeerable value)
7476 }
7577 int key = value . JniIdentityHashCode ;
7678 lock ( RegisteredInstances ) {
77- List < IJavaPeerable > ? peers ;
79+ List < GCHandle > ? peers ;
7880 if ( ! RegisteredInstances . TryGetValue ( key , out peers ) ) {
79- peers = new List < IJavaPeerable > ( ) {
80- value ,
81+ peers = new List < GCHandle > ( ) {
82+ JavaMarshal . CreateReferenceTrackingHandle ( value , value . PeerReference . Handle )
8183 } ;
8284 RegisteredInstances . Add ( key , peers ) ;
8385 return ;
8486 }
8587
8688 for ( int i = peers . Count - 1 ; i >= 0 ; i -- ) {
8789 var p = peers [ i ] ;
88- if ( ! JniEnvironment . Types . IsSameObject ( p . PeerReference , value . PeerReference ) )
90+ if ( p . Target is not IJavaPeerable peer )
91+ continue ;
92+ if ( ! JniEnvironment . Types . IsSameObject ( peer . PeerReference , value . PeerReference ) )
8993 continue ;
9094 if ( Replaceable ( p ) ) {
91- peers [ i ] = value ;
95+ peers [ i ] = JavaMarshal . CreateReferenceTrackingHandle ( value , value . PeerReference . Handle ) ;
9296 } else {
93- WarnNotReplacing ( key , value , p ) ;
97+ WarnNotReplacing ( key , value , peer ) ;
9498 }
9599 return ;
96100 }
97- peers . Add ( value ) ;
101+ peers . Add ( JavaMarshal . CreateReferenceTrackingHandle ( value , value . PeerReference . Handle ) ) ;
98102 }
99103 }
100104
101- static bool Replaceable ( IJavaPeerable peer )
105+ static bool Replaceable ( GCHandle handle )
102106 {
103- if ( peer == null )
107+ if ( handle . Target is not IJavaPeerable peer )
104108 return true ;
105109 return peer . JniManagedPeerState . HasFlag ( JniManagedPeerStates . Replaceable ) ;
106110 }
@@ -132,14 +136,14 @@ void WarnNotReplacing (int key, IJavaPeerable ignoreValue, IJavaPeerable keepVal
132136 int key = GetJniIdentityHashCode ( reference ) ;
133137
134138 lock ( RegisteredInstances ) {
135- List < IJavaPeerable > ? peers ;
139+ List < GCHandle > ? peers ;
136140 if ( ! RegisteredInstances . TryGetValue ( key , out peers ) )
137141 return null ;
138142
139143 for ( int i = peers . Count - 1 ; i >= 0 ; i -- ) {
140144 var p = peers [ i ] ;
141- if ( JniEnvironment . Types . IsSameObject ( reference , p . PeerReference ) )
142- return p ;
145+ if ( p . Target is IJavaPeerable peer && JniEnvironment . Types . IsSameObject ( reference , peer . PeerReference ) )
146+ return peer ;
143147 }
144148 if ( peers . Count == 0 )
145149 RegisteredInstances . Remove ( key ) ;
@@ -157,13 +161,13 @@ public override void RemovePeer (IJavaPeerable value)
157161
158162 int key = value . JniIdentityHashCode ;
159163 lock ( RegisteredInstances ) {
160- List < IJavaPeerable > ? peers ;
164+ List < GCHandle > ? peers ;
161165 if ( ! RegisteredInstances . TryGetValue ( key , out peers ) )
162166 return ;
163167
164168 for ( int i = peers . Count - 1 ; i >= 0 ; i -- ) {
165169 var p = peers [ i ] ;
166- if ( object . ReferenceEquals ( value , p ) ) {
170+ if ( object . ReferenceEquals ( value , p . Target ) ) {
167171 peers . RemoveAt ( i ) ;
168172 }
169173 }
@@ -251,7 +255,9 @@ public override List<JniSurfacedPeerInfo> GetSurfacedPeers ()
251255 var peers = new List < JniSurfacedPeerInfo > ( RegisteredInstances . Count ) ;
252256 foreach ( var e in RegisteredInstances ) {
253257 foreach ( var p in e . Value ) {
254- peers . Add ( new JniSurfacedPeerInfo ( e . Key , new WeakReference < IJavaPeerable > ( p ) ) ) ;
258+ if ( p . Target is not IJavaPeerable peer )
259+ continue ;
260+ peers . Add ( new JniSurfacedPeerInfo ( e . Key , new WeakReference < IJavaPeerable > ( peer ) ) ) ;
255261 }
256262 }
257263 return peers ;
0 commit comments