Skip to content

Commit c7657d7

Browse files
committed
Flushity Flush
Context: #9921 (comment) Do tests pass without crashing? If the tests *do* crash, next step is to *revert* changes to `AndroidRuntime.cs`. This should re-introduce failures within `CreatePeer_ReplaceableDoesNotReplace()`, but would narrow down what may be in play.
1 parent 1cfb970 commit c7657d7

File tree

6 files changed

+37
-12
lines changed

6 files changed

+37
-12
lines changed

src/Mono.Android/Android.Runtime/AndroidRuntime.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,13 @@ public override IntPtr ReleaseLocalReference (ref JniObjectReference value, ref
173173
public override void WriteLocalReferenceLine (string format, params object?[] args)
174174
{
175175
RuntimeNativeMethods._monodroid_gref_log ("[LREF] " + string.Format (CultureInfo.InvariantCulture, format, args));
176+
RuntimeNativeMethods._monodroid_gref_log ("\n");
176177
}
177178

178179
public override void WriteGlobalReferenceLine (string format, params object?[] args)
179180
{
180181
RuntimeNativeMethods._monodroid_gref_log (string.Format (CultureInfo.InvariantCulture, format, args));
182+
RuntimeNativeMethods._monodroid_gref_log ("\n");
181183
}
182184

183185
public override JniObjectReference CreateGlobalReference (JniObjectReference value)
@@ -689,7 +691,7 @@ internal void AddPeer (IJavaPeerable value, JniObjectReference reference, IntPtr
689691
for (int i = 0; i < targets.Count; ++i) {
690692
IJavaPeerable? target;
691693
var wref = targets [i];
692-
if (ShouldReplaceMapping (wref!, reference, out target)) {
694+
if (ShouldReplaceMapping (wref!, reference, value, out target)) {
693695
found = true;
694696
targets [i] = IdentityHashTargets.CreateWeakReference (value);
695697
break;
@@ -747,7 +749,7 @@ internal void AddPeer (IJavaPeerable value, IntPtr handle, JniHandleOwnership tr
747749
}
748750
}
749751

750-
bool ShouldReplaceMapping (WeakReference<IJavaPeerable> current, JniObjectReference reference, out IJavaPeerable? target)
752+
bool ShouldReplaceMapping (WeakReference<IJavaPeerable> current, JniObjectReference reference, IJavaPeerable value, out IJavaPeerable? target)
751753
{
752754
target = null;
753755

@@ -771,12 +773,17 @@ bool ShouldReplaceMapping (WeakReference<IJavaPeerable> current, JniObjectRefere
771773
// we want the 2nd MCW to replace the 1st, as the 2nd is
772774
// the one the dev created; the 1st is an implicit intermediary.
773775
//
776+
// Meanwhile, a new "replaceable" instance should *not* replace an
777+
// existing "replaceable" instance; see dotnet/android#9862.
778+
//
774779
// [0]: If Java ctor invokes overridden virtual method, we'll
775780
// transition into managed code w/o a registered instance, and
776781
// thus will create an "intermediary" via
777782
// (IntPtr, JniHandleOwnership) .ctor.
778-
if ((target.JniManagedPeerState & JniManagedPeerStates.Replaceable) == JniManagedPeerStates.Replaceable)
783+
if (target.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable) &&
784+
!value.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable)) {
779785
return true;
786+
}
780787

781788
return false;
782789
}

src/Mono.Android/Android.Runtime/JNIEnv.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,7 @@ static int _GetArrayLength (IntPtr array_ptr)
10701070
ret [i] = targetType == null || targetType.IsInstanceOfType (value)
10711071
? value
10721072
: Convert.ChangeType (value, targetType, CultureInfo.InvariantCulture);
1073+
GC.KeepAlive (value);
10731074
}
10741075

10751076
return ret;

src/Mono.Android/Java.Interop/TypeManager.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,6 @@ static Type monovm_typemap_java_to_managed (string java_type_name)
359359

360360
try {
361361
result = (IJavaPeerable) CreateProxy (type, handle, transfer);
362-
if (Runtime.IsGCUserPeer (result.PeerReference.Handle)) {
363-
result.SetJniManagedPeerState (JniManagedPeerStates.Replaceable | JniManagedPeerStates.Activatable);
364-
}
365362
} catch (MissingMethodException e) {
366363
var key_handle = JNIEnv.IdentityHash (handle);
367364
JNIEnv.DeleteRef (handle, transfer);
@@ -385,19 +382,31 @@ internal static object CreateProxy (
385382
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
386383
var c = type.GetConstructor (flags, null, XAConstructorSignature, null);
387384
if (c != null) {
388-
return c.Invoke (new object [] { handle, transfer });
385+
var self = GetUninitializedObject (type);
386+
c.Invoke (self, new object [] { handle, transfer });
387+
return self;
389388
}
390389
c = type.GetConstructor (flags, null, JIConstructorSignature, null);
391390
if (c != null) {
391+
var self = GetUninitializedObject (type);
392392
JniObjectReference r = new JniObjectReference (handle);
393393
JniObjectReferenceOptions o = JniObjectReferenceOptions.Copy;
394-
var peer = (IJavaPeerable) c.Invoke (new object [] { r, o });
394+
c.Invoke (self, new object [] { r, o });
395395
JNIEnv.DeleteRef (handle, transfer);
396-
return peer;
396+
return self;
397397
}
398398
throw new MissingMethodException (
399399
"No constructor found for " + type.FullName + "::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)",
400400
CreateJavaLocationException ());
401+
402+
static IJavaPeerable GetUninitializedObject (
403+
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
404+
Type type)
405+
{
406+
var v = (IJavaPeerable) System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject (type);
407+
v.SetJniManagedPeerState (JniManagedPeerStates.Replaceable | JniManagedPeerStates.Activatable);
408+
return v;
409+
}
401410
}
402411

403412
public static void RegisterType (string java_class, Type t)

src/native/mono/runtime-base/util.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,10 @@ Util::path_combine (const char *path1, const char *path2)
147147
void
148148
Util::create_public_directory (const char *dir)
149149
{
150-
mode_t m = umask (0);
151-
int ret = mkdir (dir, 0777);
150+
int ret = create_directory (dir, 0777);
152151
if (ret < 0) {
153152
log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno));
154153
}
155-
umask (m);
156154
}
157155

158156
int

tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
<_DefaultValueAttributeSupport Condition="'$(TrimMode)' == 'full'">true</_DefaultValueAttributeSupport>
4747
</PropertyGroup>
4848

49+
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
50+
<!-- trying to track:
51+
JNI ERROR (app bug): accessed deleted Global 0x3056
52+
-->
53+
<AndroidEnvironment Include="env.txt" />
54+
</ItemGroup>
55+
4956
<ItemGroup>
5057
<ProjectReference Include="..\..\TestRunner.Core\TestRunner.Core.NET.csproj" />
5158
<ProjectReference Include="..\..\TestRunner.NUnit\TestRunner.NUnit.NET.csproj" />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Environment Variables and system properties
2+
# debug.mono.log=gref,default
3+
debug.mono.debug=1

0 commit comments

Comments
 (0)