From 24cea9cb7469940d214dba7d9ded9f25bc97adde Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Tue, 19 Jan 2021 22:08:40 +0100 Subject: [PATCH 1/3] Add ActivatePeer to JniValueManager To allow different implementation of creating the activator/constructor methods on desktop and mobile. The goal is to avoid using SLE in mobile version, to improve linking. --- .../JniRuntime.JniValueManager.cs | 2 + src/Java.Interop/Java.Interop/ManagedPeer.cs | 43 +------------- src/Java.Interop/Properties/AssemblyInfo.cs | 7 +++ .../Java.Interop/MonoRuntimeValueManager.cs | 58 ++++++++++++++++++- 4 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs index 95b907ea4..3b67dc451 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs @@ -86,6 +86,8 @@ protected virtual void Dispose (bool disposing) public abstract List GetSurfacedPeers (); + public abstract void ActivatePeer (JniObjectReference reference, Type peerType, Type []? constructorArguments, object? []? argumentValues); + public void ConstructPeer (IJavaPeerable peer, ref JniObjectReference reference, JniObjectReferenceOptions options) { if (peer == null) diff --git a/src/Java.Interop/Java.Interop/ManagedPeer.cs b/src/Java.Interop/Java.Interop/ManagedPeer.cs index 121e11c87..ce1a9c821 100644 --- a/src/Java.Interop/Java.Interop/ManagedPeer.cs +++ b/src/Java.Interop/Java.Interop/ManagedPeer.cs @@ -93,31 +93,8 @@ static void Construct ( var ptypes = GetParameterTypes (JniEnvironment.Strings.ToString (n_constructorSignature)); var pvalues = GetValues (runtime, new JniObjectReference (n_constructorArguments), ptypes); - var ctor = type.GetConstructors (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - .FirstOrDefault (c => - c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (ptypes)); - if (ctor == null) { - throw CreateMissingConstructorException (type, ptypes); - } - if (self != null) { - ctor.Invoke (self, pvalues); - return; - } - try { - var f = JniEnvironment.Runtime.MarshalMemberBuilder.CreateConstructActivationPeerFunc (ctor); - f (ctor, new JniObjectReference (n_self), pvalues); - } - catch (Exception e) { - var m = string.Format ("Could not activate {{ PeerReference={0} IdentityHashCode=0x{1} Java.Type={2} }} for managed type '{3}'.", - r_self, - runtime.ValueManager.GetJniIdentityHashCode (r_self).ToString ("x"), - JniEnvironment.Types.GetJniTypeNameFromInstance (r_self), - type.FullName); - Debug.WriteLine (m); - - throw new NotSupportedException (m, e); - } + JniEnvironment.Runtime.ValueManager.ActivatePeer (new JniObjectReference (n_self), type, ptypes, pvalues); } catch (Exception e) when (JniEnvironment.Runtime.ExceptionShouldTransitionToJni (e)) { envp.SetPendingException (e); @@ -134,22 +111,6 @@ static Exception CreateJniLocationException () } } - static Exception CreateMissingConstructorException (Type type, Type[] ptypes) - { - var message = new StringBuilder (); - message.Append ("Unable to find constructor "); - message.Append (type.FullName); - message.Append ("("); - if (ptypes.Length > 0) { - message.Append (ptypes [0].FullName); - for (int i = 1; i < ptypes.Length; ++i) - message.Append (", ").Append (ptypes [i].FullName); - } - message.Append (")"); - message.Append (". Please provide the missing constructor."); - return new NotSupportedException (message.ToString (), CreateJniLocationException ()); - } - static Type[] GetParameterTypes (string? signature) { if (string.IsNullOrEmpty (signature)) @@ -210,7 +171,7 @@ static void RegisterNativeMembers ( } } - sealed class JniLocationException : Exception { + internal sealed class JniLocationException : Exception { string stackTrace; diff --git a/src/Java.Interop/Properties/AssemblyInfo.cs b/src/Java.Interop/Properties/AssemblyInfo.cs index 7b392dd50..b599f355d 100644 --- a/src/Java.Interop/Properties/AssemblyInfo.cs +++ b/src/Java.Interop/Properties/AssemblyInfo.cs @@ -28,3 +28,10 @@ "814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0" + "d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b" + "2c9733db")] +[assembly: InternalsVisibleTo ( + "Java.Runtime.Environment, PublicKey=" + + "0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf1" + + "6cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2" + + "814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0" + + "d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b" + + "2c9733db")] diff --git a/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs b/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs index b64864a29..d39f50ce2 100644 --- a/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs +++ b/src/Java.Runtime.Environment/Java.Interop/MonoRuntimeValueManager.cs @@ -1,7 +1,11 @@ -using System; +using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Text; namespace Java.Interop { @@ -229,6 +233,58 @@ public override IJavaPeerable PeekPeer (JniObjectReference reference) return null; } + static Exception CreateMissingConstructorException (Type type, Type [] ptypes) + { + var message = new StringBuilder (); + message.Append ("Unable to find constructor "); + message.Append (type.FullName); + message.Append ("("); + if (ptypes.Length > 0) { + message.Append (ptypes [0].FullName); + for (int i = 1; i < ptypes.Length; ++i) + message.Append (", ").Append (ptypes [i].FullName); + } + message.Append (")"); + message.Append (". Please provide the missing constructor."); + return new NotSupportedException (message.ToString (), CreateJniLocationException ()); + } + + static Exception CreateJniLocationException () + { + using (var e = new JavaException ()) { + return new JniLocationException (e.ToString ()); + } + } + + public override void ActivatePeer (JniObjectReference reference, Type peerType, Type [] constructorArguments, object [] argumentValues) + { + var ctor = peerType.GetConstructors (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + .FirstOrDefault (c => c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (constructorArguments)); + if (ctor == null) { + throw CreateMissingConstructorException (peerType, constructorArguments); + } + var runtime = JniEnvironment.Runtime; + var self = runtime.ValueManager.PeekPeer (reference); + if (self != null) { + ctor.Invoke (self, argumentValues); + return; + } + + try { + var f = JniEnvironment.Runtime.MarshalMemberBuilder.CreateConstructActivationPeerFunc (ctor); + f (ctor, reference, 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), + peerType.FullName); + Debug.WriteLine (m); + + throw new NotSupportedException (m, e); + } + } + public override void FinalizePeer (IJavaPeerable value) { var h = value.PeerReference; From 1875ea74e024d1286f30afa6018983bfd8835159 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Tue, 19 Jan 2021 23:12:34 +0100 Subject: [PATCH 2/3] Add ActivatePeer to ProxyValueManager --- tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs b/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs index b7f81102e..705473cc6 100644 --- a/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs +++ b/tests/Java.Interop-Tests/Java.Interop/JniRuntimeTest.cs @@ -151,6 +151,11 @@ public override IJavaPeerable PeekPeer (JniObjectReference reference) return null; } + public override void ActivatePeer (JniObjectReference reference, Type peerType, Type [] constructorArguments, object [] argumentValues) + { + throw new NotImplementedException (); + } + public override void RemovePeer (IJavaPeerable peer) { } From 47c20cfc2a3f4c3df88bf57528a73465fadecbce Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Tue, 19 Jan 2021 23:15:47 +0100 Subject: [PATCH 3/3] Add ActivatePeer to MyValueManager --- .../Java.Interop/JniRuntime.JniValueManagerTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs b/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs index 2e865c225..3ffb807fb 100644 --- a/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs +++ b/tests/Java.Interop-Tests/Java.Interop/JniRuntime.JniValueManagerTests.cs @@ -59,6 +59,11 @@ public override IJavaPeerable PeekPeer (JniObjectReference reference) { return null; } + + public override void ActivatePeer (JniObjectReference reference, Type peerType, Type [] constructorArguments, object [] argumentValues) + { + throw new NotImplementedException (); + } } [Test]