diff --git a/external/Java.Interop b/external/Java.Interop index 8221b7d0d85..d3d3a1bf820 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 8221b7d0d8599fc793e3d55ee802c14deb6da07c +Subproject commit d3d3a1bf8200cbcc545ac438c47abcd158b55a1e diff --git a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs index b1390a5f884..8af0d4127b4 100644 --- a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs +++ b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs @@ -173,11 +173,13 @@ public override IntPtr ReleaseLocalReference (ref JniObjectReference value, ref public override void WriteLocalReferenceLine (string format, params object?[] args) { RuntimeNativeMethods._monodroid_gref_log ("[LREF] " + string.Format (CultureInfo.InvariantCulture, format, args)); + RuntimeNativeMethods._monodroid_gref_log ("\n"); } public override void WriteGlobalReferenceLine (string format, params object?[] args) { RuntimeNativeMethods._monodroid_gref_log (string.Format (CultureInfo.InvariantCulture, format, args)); + RuntimeNativeMethods._monodroid_gref_log ("\n"); } public override JniObjectReference CreateGlobalReference (JniObjectReference value) @@ -689,7 +691,7 @@ internal void AddPeer (IJavaPeerable value, JniObjectReference reference, IntPtr for (int i = 0; i < targets.Count; ++i) { IJavaPeerable? target; var wref = targets [i]; - if (ShouldReplaceMapping (wref!, reference, out target)) { + if (ShouldReplaceMapping (wref!, reference, value, out target)) { found = true; targets [i] = IdentityHashTargets.CreateWeakReference (value); break; @@ -747,7 +749,7 @@ internal void AddPeer (IJavaPeerable value, IntPtr handle, JniHandleOwnership tr } } - bool ShouldReplaceMapping (WeakReference current, JniObjectReference reference, out IJavaPeerable? target) + bool ShouldReplaceMapping (WeakReference current, JniObjectReference reference, IJavaPeerable value, out IJavaPeerable? target) { target = null; @@ -771,12 +773,17 @@ bool ShouldReplaceMapping (WeakReference current, JniObjectRefere // we want the 2nd MCW to replace the 1st, as the 2nd is // the one the dev created; the 1st is an implicit intermediary. // + // Meanwhile, a new "replaceable" instance should *not* replace an + // existing "replaceable" instance; see dotnet/android#9862. + // // [0]: If Java ctor invokes overridden virtual method, we'll // transition into managed code w/o a registered instance, and // thus will create an "intermediary" via // (IntPtr, JniHandleOwnership) .ctor. - if ((target.JniManagedPeerState & JniManagedPeerStates.Replaceable) == JniManagedPeerStates.Replaceable) + if (target.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable) && + !value.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable)) { return true; + } return false; } diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index 81ee5d6da47..adc07f0edb1 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -382,22 +382,34 @@ internal static object CreateProxy ( { // Skip Activator.CreateInstance() as that requires public constructors, // and we want to hide some constructors for sanity reasons. + var peer = GetUninitializedObject (type); BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var c = type.GetConstructor (flags, null, XAConstructorSignature, null); if (c != null) { - return c.Invoke (new object [] { handle, transfer }); + c.Invoke (peer, new object[] { handle, transfer }); + return peer; } c = type.GetConstructor (flags, null, JIConstructorSignature, null); if (c != null) { JniObjectReference r = new JniObjectReference (handle); JniObjectReferenceOptions o = JniObjectReferenceOptions.Copy; - var peer = (IJavaPeerable) c.Invoke (new object [] { r, o }); + c.Invoke (peer, new object [] { r, o }); JNIEnv.DeleteRef (handle, transfer); return peer; } + GC.SuppressFinalize (peer); throw new MissingMethodException ( "No constructor found for " + type.FullName + "::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)", CreateJavaLocationException ()); + + static IJavaPeerable GetUninitializedObject ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + Type type) + { + var v = (IJavaPeerable) System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject (type); + v.SetJniManagedPeerState (JniManagedPeerStates.Replaceable | JniManagedPeerStates.Activatable); + return v; + } } public static void RegisterType (string java_class, Type t) diff --git a/src/Mono.Android/Java.Lang/Object.cs b/src/Mono.Android/Java.Lang/Object.cs index 9e58768d9ee..58a7e54d88b 100644 --- a/src/Mono.Android/Java.Lang/Object.cs +++ b/src/Mono.Android/Java.Lang/Object.cs @@ -110,13 +110,22 @@ protected override void Dispose (bool disposing) protected void SetHandle (IntPtr value, JniHandleOwnership transfer) { var reference = new JniObjectReference (value); + var options = FromJniHandleOwnership (transfer); JNIEnvInit.ValueManager?.ConstructPeer ( this, ref reference, - value == IntPtr.Zero ? JniObjectReferenceOptions.None : JniObjectReferenceOptions.Copy); + value == IntPtr.Zero ? JniObjectReferenceOptions.None : options); JNIEnv.DeleteRef (value, transfer); } + static JniObjectReferenceOptions FromJniHandleOwnership (JniHandleOwnership transfer) + { + var options = JniObjectReferenceOptions.Copy; + if (transfer.HasFlag (JniHandleOwnership.DoNotRegister)) + options |= JniObjectReferenceOptions.CopyAndDoNotRegister; + return options; + } + internal static IJavaPeerable? PeekObject (IntPtr handle, Type? requiredType = null) { var peeked = JNIEnvInit.ValueManager?.PeekPeer (new JniObjectReference (handle)); diff --git a/src/Mono.Android/Microsoft.Android.Runtime/ManagedValueManager.cs b/src/Mono.Android/Microsoft.Android.Runtime/ManagedValueManager.cs index 616217ca4bc..88600bb0929 100644 --- a/src/Mono.Android/Microsoft.Android.Runtime/ManagedValueManager.cs +++ b/src/Mono.Android/Microsoft.Android.Runtime/ManagedValueManager.cs @@ -265,7 +265,8 @@ public override List GetSurfacedPeers () static readonly Type[] XAConstructorSignature = new Type [] { typeof (IntPtr), typeof (JniHandleOwnership) }; - protected override IJavaPeerable? TryCreatePeer ( + protected override bool TryConstructPeer ( + IJavaPeerable self, ref JniObjectReference reference, JniObjectReferenceOptions options, [DynamicallyAccessedMembers (Constructors)] @@ -277,10 +278,10 @@ public override List GetSurfacedPeers () reference.Handle, JniHandleOwnership.DoNotTransfer, }; - var p = (IJavaPeerable) c.Invoke (args); + c.Invoke (self, args); JniObjectReference.Dispose (ref reference, options); - return p; + return true; } - return base.TryCreatePeer (ref reference, options, type); + return base.TryConstructPeer (self, ref reference, options, type); } } diff --git a/src/native/mono/runtime-base/util.cc b/src/native/mono/runtime-base/util.cc index 3e805c34f9b..fda41ecfd88 100644 --- a/src/native/mono/runtime-base/util.cc +++ b/src/native/mono/runtime-base/util.cc @@ -147,12 +147,10 @@ Util::path_combine (const char *path1, const char *path2) void Util::create_public_directory (const char *dir) { - mode_t m = umask (0); - int ret = mkdir (dir, 0777); + int ret = create_directory (dir, 0777); if (ret < 0) { log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno)); } - umask (m); } int diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj index 7856cb38d1b..b762c8be98e 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj @@ -52,6 +52,13 @@ <_DefaultValueAttributeSupport Condition="'$(TrimMode)' == 'full'">true + + + + + diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt b/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt new file mode 100644 index 00000000000..cb897b79238 --- /dev/null +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt @@ -0,0 +1,3 @@ +# Environment Variables and system properties +# debug.mono.log=gref,default +debug.mono.debug=1