From c676a111613369f40414d228c08444ea03a8736d Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Fri, 12 Jun 2026 18:07:01 +0200 Subject: [PATCH 1/2] Make TryConstructPeer virtual --- .../Java.Interop/JniRuntime.ReflectionJniValueManager.cs | 4 ++-- src/Java.Interop/PublicAPI.Unshipped.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs index 70ba47414..e6b52a168 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs @@ -233,7 +233,7 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type) static readonly Type ByRefJniObjectReference = typeof (JniObjectReference).MakeByRefType (); static readonly Type[] JIConstructorSignature = new Type [] { ByRefJniObjectReference, typeof (JniObjectReferenceOptions) }; - bool TryConstructPeer ( + protected virtual bool TryConstructPeer ( IJavaPeerable self, ref JniObjectReference reference, JniObjectReferenceOptions options, @@ -247,7 +247,7 @@ bool TryConstructPeer ( options, }; c.Invoke (self, args); - reference = (JniObjectReference) args [0]; + JniObjectReference.Dispose (ref reference, options); return true; } return false; diff --git a/src/Java.Interop/PublicAPI.Unshipped.txt b/src/Java.Interop/PublicAPI.Unshipped.txt index de95bcd1d..2051fd1e8 100644 --- a/src/Java.Interop/PublicAPI.Unshipped.txt +++ b/src/Java.Interop/PublicAPI.Unshipped.txt @@ -85,3 +85,4 @@ override Java.Interop.JniRuntime.ReflectionJniTypeManager.GetTypes(Java.Interop. override Java.Interop.JniRuntime.ReflectionJniTypeManager.GetTypesForSimpleReference(string! jniSimpleReference) -> System.Collections.Generic.IEnumerable! override Java.Interop.JniRuntime.ReflectionJniTypeManager.RegisterNativeMembers(Java.Interop.JniType! nativeClass, System.Type! type, string? methods) -> void override Java.Interop.JniRuntime.ReflectionJniTypeManager.RegisterNativeMembers(Java.Interop.JniType! nativeClass, System.Type! type, System.ReadOnlySpan methods) -> void +virtual Java.Interop.JniRuntime.ReflectionJniValueManager.TryConstructPeer(Java.Interop.IJavaPeerable! self, ref Java.Interop.JniObjectReference reference, Java.Interop.JniObjectReferenceOptions options, System.Type! type) -> bool From d91d21431dabec43dd08a63f9267b092274bfb5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:24:12 +0000 Subject: [PATCH 2/2] Fix double-dispose in TryConstructPeer by syncing reference from args[0] after reflection invoke Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> --- .../Java.Interop/JniRuntime.ReflectionJniValueManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs index e6b52a168..3282e906d 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.ReflectionJniValueManager.cs @@ -247,6 +247,7 @@ protected virtual bool TryConstructPeer ( options, }; c.Invoke (self, args); + reference = (JniObjectReference) args [0]; JniObjectReference.Dispose (ref reference, options); return true; }