From f7fa39e2835086b2f000639b5b9f5d0ceeb76505 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 20 May 2026 15:08:54 +0200 Subject: [PATCH 1/2] Change the signature of JniValueManager.ActivatePeer --- .../JniRuntime.JniValueManager.cs | 26 +++++++++++++- src/Java.Interop/Java.Interop/ManagedPeer.cs | 2 +- src/Java.Interop/PublicAPI.Unshipped.txt | 2 ++ .../Java.Interop/ManagedValueManager.cs | 35 ------------------- .../Java.Interop/MonoRuntimeValueManager.cs | 29 --------------- .../JniRuntime.JniValueManagerTests.cs | 5 --- .../Java.Interop/JniRuntimeTest.cs | 5 --- 7 files changed, 28 insertions(+), 76 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs index 869243854..f79a63185 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -88,7 +90,29 @@ protected virtual void Dispose (bool disposing) public abstract List GetSurfacedPeers (); - public abstract void ActivatePeer (IJavaPeerable? self, JniObjectReference reference, ConstructorInfo cinfo, object? []? argumentValues); + public virtual void ActivatePeer ( + JniObjectReference reference, + [DynamicallyAccessedMembers (Constructors)] Type type, + ConstructorInfo cinfo, + object?[]? argumentValues) + { + try { + var self = (IJavaPeerable) RuntimeHelpers.GetUninitializedObject (type); + self.SetPeerReference (reference); + cinfo.Invoke (self, argumentValues); + } catch (Exception e) { + var m = string.Format ( + CultureInfo.InvariantCulture, + "Could not activate {{ PeerReference={0} IdentityHashCode=0x{1} Java.Type={2} }} for managed type '{3}'.", + reference, + GetJniIdentityHashCode (reference).ToString ("x", CultureInfo.InvariantCulture), + JniEnvironment.Types.GetJniTypeNameFromInstance (reference), + type?.FullName); + Debug.WriteLine (m); + + throw new NotSupportedException (m, e); + } + } public void ConstructPeer (IJavaPeerable peer, ref JniObjectReference reference, JniObjectReferenceOptions options) { diff --git a/src/Java.Interop/Java.Interop/ManagedPeer.cs b/src/Java.Interop/Java.Interop/ManagedPeer.cs index 6a7d6eee2..8f8027476 100644 --- a/src/Java.Interop/Java.Interop/ManagedPeer.cs +++ b/src/Java.Interop/Java.Interop/ManagedPeer.cs @@ -119,7 +119,7 @@ static void Construct ( return; } - JniEnvironment.Runtime.ValueManager.ActivatePeer (self, new JniObjectReference (n_self), cinfo, pvalues); + JniEnvironment.Runtime.ValueManager.ActivatePeer (new JniObjectReference (n_self), type, cinfo, pvalues); } catch (Exception e) { __r?.OnUserUnhandledException (ref envp, e); diff --git a/src/Java.Interop/PublicAPI.Unshipped.txt b/src/Java.Interop/PublicAPI.Unshipped.txt index 4cc773cf3..8bc1c7d30 100644 --- a/src/Java.Interop/PublicAPI.Unshipped.txt +++ b/src/Java.Interop/PublicAPI.Unshipped.txt @@ -34,3 +34,5 @@ static Java.Interop.JniEnvironment.InstanceFields.GetFieldID(Java.Interop.JniObj static Java.Interop.JniEnvironment.InstanceMethods.GetMethodID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! static Java.Interop.JniEnvironment.StaticFields.GetStaticFieldID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! static Java.Interop.JniEnvironment.StaticMethods.GetStaticMethodID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +*REMOVED*abstract Java.Interop.JniRuntime.JniValueManager.ActivatePeer(Java.Interop.IJavaPeerable? self, Java.Interop.JniObjectReference reference, System.Reflection.ConstructorInfo! cinfo, object?[]? argumentValues) -> void +abstract Java.Interop.JniRuntime.JniValueManager.ActivatePeer(Java.Interop.JniObjectReference reference, System.Type! type, System.Reflection.ConstructorInfo! cinfo, object?[]? argumentValues) -> void diff --git a/src/Java.Runtime.Environment/Java.Interop/ManagedValueManager.cs b/src/Java.Runtime.Environment/Java.Interop/ManagedValueManager.cs index 4c4cf4d37..223a0d052 100644 --- a/src/Java.Runtime.Environment/Java.Interop/ManagedValueManager.cs +++ b/src/Java.Runtime.Environment/Java.Interop/ManagedValueManager.cs @@ -198,41 +198,6 @@ public override void FinalizePeer (IJavaPeerable value) value.Finalized (); } - public override void ActivatePeer (IJavaPeerable? self, JniObjectReference reference, ConstructorInfo cinfo, object?[]? argumentValues) - { - var runtime = JniEnvironment.Runtime; - - try { - ActivateViaReflection (reference, cinfo, argumentValues); - } catch (Exception e) { - var m = string.Format ("Could not activate {{ PeerReference={0} IdentityHashCode=0x{1} Java.Type={2} }} for managed type '{3}'.", - reference, - runtime.ValueManager.GetJniIdentityHashCode (reference).ToString ("x"), - JniEnvironment.Types.GetJniTypeNameFromInstance (reference), - cinfo.DeclaringType?.FullName); - Debug.WriteLine (m); - - throw new NotSupportedException (m, e); - } - } - - void ActivateViaReflection (JniObjectReference reference, ConstructorInfo cinfo, object?[]? argumentValues) - { - var declType = cinfo.DeclaringType ?? throw new NotSupportedException ("Do not know the type to create!"); - - var self = GetUninitializedObject (declType); - self.SetPeerReference (reference); - - cinfo.Invoke (self, argumentValues); - - // FIXME: https://github.com/dotnet/java-interop/issues/1192 - const string getUninitializedObject = "This code path is not used in Android projects."; - [UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = getUninitializedObject)] - [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = getUninitializedObject)] - static IJavaPeerable GetUninitializedObject (Type type) => - (IJavaPeerable) System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject (type); - } - public override List GetSurfacedPeers () { if (RegisteredInstances == null) diff --git a/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs b/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs index 2953c799a..727354429 100644 --- a/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs +++ b/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs @@ -258,35 +258,6 @@ static Exception CreateJniLocationException () } } - const string NotUsedInAndroid = "This code path is not used in Android projects."; - - public override void ActivatePeer (IJavaPeerable? self, JniObjectReference reference, ConstructorInfo cinfo, object?[]? argumentValues) - { - var runtime = JniEnvironment.Runtime; - - try { - var declType = cinfo.DeclaringType ?? throw new NotSupportedException ("Do not know the type to create!"); - var instance = GetUninitializedObject (declType); - instance.SetPeerReference (reference); - cinfo.Invoke (instance, argumentValues); - - // FIXME: https://github.com/dotnet/java-interop/issues/1192 - [UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = NotUsedInAndroid)] - [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = NotUsedInAndroid)] - static IJavaPeerable GetUninitializedObject (Type type) => - (IJavaPeerable) System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject (type); - } catch (Exception e) { - var m = string.Format ("Could not activate {{ PeerReference={0} IdentityHashCode=0x{1} Java.Type={2} }} for managed type '{3}'.", - reference, - runtime.ValueManager.GetJniIdentityHashCode (reference).ToString ("x"), - JniEnvironment.Types.GetJniTypeNameFromInstance (reference), - cinfo.DeclaringType?.FullName); - Debug.WriteLine (m); - - throw new NotSupportedException (m, e); - } - } - public override void FinalizePeer (IJavaPeerable value) { var h = value.PeerReference; diff --git a/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs b/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs index f8f8c42bb..b687067e5 100644 --- a/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs +++ b/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs @@ -60,11 +60,6 @@ public override IJavaPeerable PeekPeer (JniObjectReference reference) { return null; } - - public override void ActivatePeer (IJavaPeerable self, JniObjectReference reference, ConstructorInfo cinfo, object [] argumentValues) - { - throw new NotImplementedException (); - } } [Test] diff --git a/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs b/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs index 8d34c6c21..f3dafc0f8 100644 --- a/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs +++ b/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs @@ -154,11 +154,6 @@ public override IJavaPeerable PeekPeer (JniObjectReference reference) return null; } - public override void ActivatePeer (IJavaPeerable self, JniObjectReference reference, ConstructorInfo cinfo, object [] argumentValues) - { - throw new NotImplementedException (); - } - public override void RemovePeer (IJavaPeerable peer) { } From 7d8f89db77bf17c74921bc35d95876e2509d0274 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 21 May 2026 00:10:01 +0200 Subject: [PATCH 2/2] Address JniValueManager API review feedback Update the unshipped public API entry to match the virtual ActivatePeer implementation and remove an unnecessary null-conditional on the annotated Type parameter. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs | 6 +++--- src/Java.Interop/PublicAPI.Unshipped.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs index f79a63185..c9a0fe54b 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs @@ -107,7 +107,7 @@ public virtual void ActivatePeer ( reference, GetJniIdentityHashCode (reference).ToString ("x", CultureInfo.InvariantCulture), JniEnvironment.Types.GetJniTypeNameFromInstance (reference), - type?.FullName); + type.FullName); Debug.WriteLine (m); throw new NotSupportedException (m, e); @@ -318,6 +318,7 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type) return CreatePeer (ref reference, JniObjectReferenceOptions.Copy, targetType); } + // This base method implementation is NOT reachable in trimmable typemap - it is featureswitch guarded public virtual IJavaPeerable? CreatePeer ( ref JniObjectReference reference, JniObjectReferenceOptions transfer, @@ -733,7 +734,7 @@ static JniValueMarshaler GetObjectArrayMarshaler (Type elementType) // FIXME: https://github.com/dotnet/java-interop/issues/1192 [UnconditionalSuppressMessage ("Trimming", "IL2060", Justification = makeGenericMethodMessage)] - [UnconditionalSuppressMessage ("Trimming", "IL3050", Justification = makeGenericMethodMessage)] + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = makeGenericMethodMessage)] static MethodInfo MakeGenericMethod (MethodInfo method, Type type) => method.MakeGenericMethod (type); @@ -988,4 +989,3 @@ public override void DestroyGenericArgumentState (object? value, ref JniValueMar } } } - diff --git a/src/Java.Interop/PublicAPI.Unshipped.txt b/src/Java.Interop/PublicAPI.Unshipped.txt index 8bc1c7d30..359f5560e 100644 --- a/src/Java.Interop/PublicAPI.Unshipped.txt +++ b/src/Java.Interop/PublicAPI.Unshipped.txt @@ -35,4 +35,4 @@ static Java.Interop.JniEnvironment.InstanceMethods.GetMethodID(Java.Interop.JniO static Java.Interop.JniEnvironment.StaticFields.GetStaticFieldID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! static Java.Interop.JniEnvironment.StaticMethods.GetStaticMethodID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! *REMOVED*abstract Java.Interop.JniRuntime.JniValueManager.ActivatePeer(Java.Interop.IJavaPeerable? self, Java.Interop.JniObjectReference reference, System.Reflection.ConstructorInfo! cinfo, object?[]? argumentValues) -> void -abstract Java.Interop.JniRuntime.JniValueManager.ActivatePeer(Java.Interop.JniObjectReference reference, System.Type! type, System.Reflection.ConstructorInfo! cinfo, object?[]? argumentValues) -> void +virtual Java.Interop.JniRuntime.JniValueManager.ActivatePeer(Java.Interop.JniObjectReference reference, System.Type! type, System.Reflection.ConstructorInfo! cinfo, object?[]? argumentValues) -> void