|
13 | 13 | using Java.Interop.Tools.TypeNameMappings; |
14 | 14 | using System.Diagnostics.CodeAnalysis; |
15 | 15 |
|
| 16 | +using RuntimeFeature = Microsoft.Android.Runtime.RuntimeFeature; |
| 17 | + |
16 | 18 | #if JAVA_INTEROP |
17 | 19 | namespace Android.Runtime { |
18 | 20 |
|
@@ -94,7 +96,9 @@ public AndroidRuntimeOptions (IntPtr jnienv, |
94 | 96 | EnvironmentPointer = jnienv; |
95 | 97 | ClassLoader = new JniObjectReference (classLoader, JniObjectReferenceType.Global); |
96 | 98 | InvocationPointer = vm; |
97 | | - ObjectReferenceManager = new AndroidObjectReferenceManager (); |
| 99 | + ObjectReferenceManager = RuntimeFeature.IsCoreClrRuntime |
| 100 | + ? new ManagedObjectReferenceManager () |
| 101 | + : new AndroidObjectReferenceManager (); |
98 | 102 | TypeManager = typeManager; |
99 | 103 | ValueManager = valueManager; |
100 | 104 | UseMarshalMemberBuilder = false; |
@@ -244,6 +248,84 @@ public override void DeleteWeakGlobalReference (ref JniObjectReference value) |
244 | 248 | } |
245 | 249 | } |
246 | 250 |
|
| 251 | + /// <summary> |
| 252 | + /// Managed object reference manager that maintains GREF and WREF counters entirely in |
| 253 | + /// managed code using Interlocked operations, avoiding all P/Invoke overhead. |
| 254 | + /// Logging uses managed TextWriter streams — no RuntimeNativeMethods calls at all. |
| 255 | + /// Used for CoreCLR; Mono uses <see cref="AndroidObjectReferenceManager"/> instead. |
| 256 | + /// </summary> |
| 257 | + internal class ManagedObjectReferenceManager : JniRuntime.JniObjectReferenceManager { |
| 258 | + |
| 259 | + int _grefc; |
| 260 | + int _weak_grefc; |
| 261 | + |
| 262 | + public override int GlobalReferenceCount => Volatile.Read (ref _grefc); |
| 263 | + public override int WeakGlobalReferenceCount => Volatile.Read (ref _weak_grefc); |
| 264 | + |
| 265 | + public override bool LogGlobalReferenceMessages => false; |
| 266 | + public override bool LogLocalReferenceMessages => false; |
| 267 | + |
| 268 | + public override void WriteLocalReferenceLine (string format, params object?[] args) |
| 269 | + { |
| 270 | + } |
| 271 | + |
| 272 | + public override void WriteGlobalReferenceLine (string format, params object?[] args) |
| 273 | + { |
| 274 | + } |
| 275 | + |
| 276 | + public override JniObjectReference CreateLocalReference (JniObjectReference value, ref int localReferenceCount) |
| 277 | + { |
| 278 | + return base.CreateLocalReference (value, ref localReferenceCount); |
| 279 | + } |
| 280 | + |
| 281 | + public override void DeleteLocalReference (ref JniObjectReference value, ref int localReferenceCount) |
| 282 | + { |
| 283 | + base.DeleteLocalReference (ref value, ref localReferenceCount); |
| 284 | + } |
| 285 | + |
| 286 | + public override void CreatedLocalReference (JniObjectReference value, ref int localReferenceCount) |
| 287 | + { |
| 288 | + base.CreatedLocalReference (value, ref localReferenceCount); |
| 289 | + } |
| 290 | + |
| 291 | + public override IntPtr ReleaseLocalReference (ref JniObjectReference value, ref int localReferenceCount) |
| 292 | + { |
| 293 | + return base.ReleaseLocalReference (ref value, ref localReferenceCount); |
| 294 | + } |
| 295 | + |
| 296 | + public override JniObjectReference CreateGlobalReference (JniObjectReference value) |
| 297 | + { |
| 298 | + var r = base.CreateGlobalReference (value); |
| 299 | + int gc = Interlocked.Increment (ref _grefc); |
| 300 | + |
| 301 | + if (gc >= JNIEnvInit.gref_gc_threshold) { |
| 302 | + Logger.Log (LogLevel.Warn, "monodroid-gc", gc + " outstanding GREFs. Performing a full GC!"); |
| 303 | + System.GC.Collect (); |
| 304 | + } |
| 305 | + |
| 306 | + return r; |
| 307 | + } |
| 308 | + |
| 309 | + public override void DeleteGlobalReference (ref JniObjectReference value) |
| 310 | + { |
| 311 | + Interlocked.Decrement (ref _grefc); |
| 312 | + base.DeleteGlobalReference (ref value); |
| 313 | + } |
| 314 | + |
| 315 | + public override JniObjectReference CreateWeakGlobalReference (JniObjectReference value) |
| 316 | + { |
| 317 | + var r = base.CreateWeakGlobalReference (value); |
| 318 | + Interlocked.Increment (ref _weak_grefc); |
| 319 | + return r; |
| 320 | + } |
| 321 | + |
| 322 | + public override void DeleteWeakGlobalReference (ref JniObjectReference value) |
| 323 | + { |
| 324 | + Interlocked.Decrement (ref _weak_grefc); |
| 325 | + base.DeleteWeakGlobalReference (ref value); |
| 326 | + } |
| 327 | + } |
| 328 | + |
247 | 329 | class AndroidTypeManager : JniRuntime.JniTypeManager { |
248 | 330 | struct JniRemappingReplacementMethod |
249 | 331 | { |
|
0 commit comments