10
10
using System . Reflection ;
11
11
using System . Runtime . CompilerServices ;
12
12
using System . Runtime . InteropServices ;
13
+ using System . Runtime . InteropServices . Java ;
13
14
using System . Threading ;
14
15
using Android . Runtime ;
15
16
using Java . Interop ;
@@ -20,7 +21,7 @@ class ManagedValueManager : JniRuntime.JniValueManager
20
21
{
21
22
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes . PublicConstructors | DynamicallyAccessedMemberTypes . NonPublicConstructors ;
22
23
23
- Dictionary < int , List < IJavaPeerable > > ? RegisteredInstances = new Dictionary < int , List < IJavaPeerable > > ( ) ;
24
+ Dictionary < int , List < GCHandle > > ? RegisteredInstances = new ( ) ;
24
25
25
26
internal ManagedValueManager ( )
26
27
{
@@ -35,7 +36,7 @@ public override void CollectPeers ()
35
36
if ( RegisteredInstances == null )
36
37
throw new ObjectDisposedException ( nameof ( ManagedValueManager ) ) ;
37
38
38
- var peers = new List < IJavaPeerable > ( ) ;
39
+ var peers = new List < GCHandle > ( ) ;
39
40
40
41
lock ( RegisteredInstances ) {
41
42
foreach ( var ps in RegisteredInstances . Values ) {
@@ -48,7 +49,8 @@ public override void CollectPeers ()
48
49
List < Exception > ? exceptions = null ;
49
50
foreach ( var peer in peers ) {
50
51
try {
51
- peer . Dispose ( ) ;
52
+ if ( peer . Target is IDisposable disposable )
53
+ disposable . Dispose ( ) ;
52
54
}
53
55
catch ( Exception e ) {
54
56
exceptions = exceptions ?? new List < Exception > ( ) ;
@@ -74,33 +76,35 @@ public override void AddPeer (IJavaPeerable value)
74
76
}
75
77
int key = value . JniIdentityHashCode ;
76
78
lock ( RegisteredInstances ) {
77
- List < IJavaPeerable > ? peers ;
79
+ List < GCHandle > ? peers ;
78
80
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 )
81
83
} ;
82
84
RegisteredInstances . Add ( key , peers ) ;
83
85
return ;
84
86
}
85
87
86
88
for ( int i = peers . Count - 1 ; i >= 0 ; i -- ) {
87
89
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 ) )
89
93
continue ;
90
94
if ( Replaceable ( p ) ) {
91
- peers [ i ] = value ;
95
+ peers [ i ] = JavaMarshal . CreateReferenceTrackingHandle ( value , value . PeerReference . Handle ) ;
92
96
} else {
93
- WarnNotReplacing ( key , value , p ) ;
97
+ WarnNotReplacing ( key , value , peer ) ;
94
98
}
95
99
return ;
96
100
}
97
- peers . Add ( value ) ;
101
+ peers . Add ( JavaMarshal . CreateReferenceTrackingHandle ( value , value . PeerReference . Handle ) ) ;
98
102
}
99
103
}
100
104
101
- static bool Replaceable ( IJavaPeerable peer )
105
+ static bool Replaceable ( GCHandle handle )
102
106
{
103
- if ( peer == null )
107
+ if ( handle . Target is not IJavaPeerable peer )
104
108
return true ;
105
109
return peer . JniManagedPeerState . HasFlag ( JniManagedPeerStates . Replaceable ) ;
106
110
}
@@ -132,14 +136,14 @@ void WarnNotReplacing (int key, IJavaPeerable ignoreValue, IJavaPeerable keepVal
132
136
int key = GetJniIdentityHashCode ( reference ) ;
133
137
134
138
lock ( RegisteredInstances ) {
135
- List < IJavaPeerable > ? peers ;
139
+ List < GCHandle > ? peers ;
136
140
if ( ! RegisteredInstances . TryGetValue ( key , out peers ) )
137
141
return null ;
138
142
139
143
for ( int i = peers . Count - 1 ; i >= 0 ; i -- ) {
140
144
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 ;
143
147
}
144
148
if ( peers . Count == 0 )
145
149
RegisteredInstances . Remove ( key ) ;
@@ -157,13 +161,13 @@ public override void RemovePeer (IJavaPeerable value)
157
161
158
162
int key = value . JniIdentityHashCode ;
159
163
lock ( RegisteredInstances ) {
160
- List < IJavaPeerable > ? peers ;
164
+ List < GCHandle > ? peers ;
161
165
if ( ! RegisteredInstances . TryGetValue ( key , out peers ) )
162
166
return ;
163
167
164
168
for ( int i = peers . Count - 1 ; i >= 0 ; i -- ) {
165
169
var p = peers [ i ] ;
166
- if ( object . ReferenceEquals ( value , p ) ) {
170
+ if ( object . ReferenceEquals ( value , p . Target ) ) {
167
171
peers . RemoveAt ( i ) ;
168
172
}
169
173
}
@@ -251,7 +255,9 @@ public override List<JniSurfacedPeerInfo> GetSurfacedPeers ()
251
255
var peers = new List < JniSurfacedPeerInfo > ( RegisteredInstances . Count ) ;
252
256
foreach ( var e in RegisteredInstances ) {
253
257
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 ) ) ) ;
255
261
}
256
262
}
257
263
return peers ;
0 commit comments