Bug 59235 - [mono-2017-06] android.runtime.JavaProxyThrowable: System.ObjectDisposedException: Cannot access a disposed object.
Summary: [mono-2017-06] android.runtime.JavaProxyThrowable: System.ObjectDisposedExcep...
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler (show other bugs)
Version: unspecified
Hardware: PC Mac OS
: --- normal
Target Milestone: 15.5
Assignee: Bernhard Urban
URL:
Depends on:
Blocks:
 
Reported: 2017-09-05 16:36 UTC by Bernhard Urban
Modified: 2017-09-07 10:02 UTC (History)
4 users (show)

Tags: mono-2017-06
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Bernhard Urban 2017-09-05 16:36:11 UTC
I/mono-stdout( 2709): 	InnerExceptionIsSet Passed
		    I/mono-stdout( 2709): ExceptionTest : 15.403 ms
		    I/mono-stdout( 2709): HandlerTest
		    I/monodroid-timing( 2709): Runtime.register: start time: 1504530876326 ms
		    I/monodroid-timing( 2709): JNIEnv.RegisterJniNatives ("Java.Lang.Runnable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065", 0xa1d50e24) start: 1504530876326.93
		    I/monodroid-timing( 2709): JNIEnv.RegisterJniNatives total time: 1504530876327.08 [elapsed: 0.148 ms]
		    I/monodroid-timing( 2709): Runtime.register: end time: 1504530876327 [elapsed 1 ms]
		    D/Mono    ( 2709): DllImport searching in: '__Internal' ('(null)').
		    D/Mono    ( 2709): Searching for 'java_interop_jnienv_call_nonvirtual_int_method_a'.
		    D/Mono    ( 2709): Probing 'java_interop_jnienv_call_nonvirtual_int_method_a'.
		    D/Mono    ( 2709): Found as 'java_interop_jnienv_call_nonvirtual_int_method_a'.
		    I/MonoDroid( 2709): UNHANDLED EXCEPTION:
		    I/mono-stdout( 2709): 	RemoveDisposedInstance Passed
		    I/mono-stdout( 2709): HandlerTest : 15.305 ms
		    I/mono-stdout( 2709): TimeZoneTest
		    I/MonoDroid( 2709): System.ObjectDisposedException: Cannot access a disposed object.
		    I/MonoDroid( 2709): Object name: 'Java.Lang.Runnable'.
		    I/MonoDroid( 2709):   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <02673ec0d04c46ea85d735718099f909>:0 
		    I/MonoDroid( 2709):   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <02673ec0d04c46ea85d735718099f909>:0 
		    I/MonoDroid( 2709):   at Java.Lang.Object.GetHashCode () [0x0000a] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    I/MonoDroid( 2709):   at System.Delegate.GetHashCode () [0x00023] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    I/MonoDroid( 2709):   at System.MulticastDelegate.GetHashCode () [0x00000] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    I/MonoDroid( 2709):   at System.Collections.Generic.ObjectEqualityComparer`1[T].GetHashCode (T obj) [0x0000a] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    I/MonoDroid( 2709):   at System.Collections.Generic.Dictionary`2[TKey,TValue].Remove (TKey key) [0x0001e] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    I/MonoDroid( 2709):   at Java.Lang.Thread+RunnableImplementor.Run () [0x0002b] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    I/MonoDroid( 2709):   at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    I/MonoDroid( 2709):   at (wrapper dynamic-method) System.Object:c66d85c0-2fc5-4ece-a7a6-bc077f553278 (intptr,intptr)
		    --------- beginning of crash
		    E/AndroidRuntime( 2709): FATAL EXCEPTION: RemoveDisposedInstance
		    E/AndroidRuntime( 2709): Process: Mono.Android_Tests, PID: 2709
		    E/AndroidRuntime( 2709): android.runtime.JavaProxyThrowable: System.ObjectDisposedException: Cannot access a disposed object.
		    E/AndroidRuntime( 2709): Object name: 'Java.Lang.Runnable'.
		    E/AndroidRuntime( 2709):   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <02673ec0d04c46ea85d735718099f909>:0 
		    E/AndroidRuntime( 2709):   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <02673ec0d04c46ea85d735718099f909>:0 
		    E/AndroidRuntime( 2709):   at Java.Lang.Object.GetHashCode () [0x0000a] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    E/AndroidRuntime( 2709):   at System.Delegate.GetHashCode () [0x00023] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    E/AndroidRuntime( 2709):   at System.MulticastDelegate.GetHashCode () [0x00000] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    E/AndroidRuntime( 2709):   at System.Collections.Generic.ObjectEqualityComparer`1[T].GetHashCode (T obj) [0x0000a] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    E/AndroidRuntime( 2709):   at System.Collections.Generic.Dictionary`2[TKey,TValue].Remove (TKey key) [0x0001e] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    E/AndroidRuntime( 2709):   at Java.Lang.Thread+RunnableImplementor.Run () [0x0002b] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    E/AndroidRuntime( 2709):   at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    E/AndroidRuntime( 2709):   at (wrapper dynamic-method) System.Object:c66d85c0-2fc5-4ece-a7a6-bc077f553278 (intptr,intptr)
		    E/AndroidRuntime( 2709): 	at mono.java.lang.RunnableImplementor.n_run(Native Method)
		    E/AndroidRuntime( 2709): 	at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:30)
		    E/AndroidRuntime( 2709): 	at android.os.Handler.handleCallback(Handler.java:739)
		    E/AndroidRuntime( 2709): 	at android.os.Handler.dispatchMessage(Handler.java:95)
		    E/AndroidRuntime( 2709): 	at android.os.Looper.loop(Looper.java:135)
		    E/AndroidRuntime( 2709): 	at android.os.HandlerThread.run(HandlerThread.java:61)
		    W/ActivityManager( 1502): Error in app Mono.Android_Tests running instrumentation ComponentInfo{Mono.Android_Tests/xamarin.android.runtimetests.TestInstrumentation}:
		    W/ActivityManager( 1502):   android.runtime.JavaProxyThrowable
		    W/ActivityManager( 1502):   android.runtime.JavaProxyThrowable: System.ObjectDisposedException: Cannot access a disposed object.
		    W/ActivityManager( 1502): Object name: 'Java.Lang.Runnable'.
		    W/ActivityManager( 1502):   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <02673ec0d04c46ea85d735718099f909>:0 
		    W/ActivityManager( 1502):   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <02673ec0d04c46ea85d735718099f909>:0 
		    W/ActivityManager( 1502):   at Java.Lang.Object.GetHashCode () [0x0000a] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    W/ActivityManager( 1502):   at System.Delegate.GetHashCode () [0x00023] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    W/ActivityManager( 1502):   at System.MulticastDelegate.GetHashCode () [0x00000] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    W/ActivityManager( 1502):   at System.Collections.Generic.ObjectEqualityComparer`1[T].GetHashCode (T obj) [0x0000a] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    W/ActivityManager( 1502):   at System.Collections.Generic.Dictionary`2[TKey,TValue].Remove (TKey key) [0x0001e] in <1fd9ddf6108f4f659a582583057a6285>:0 
		    W/ActivityManager( 1502):   at Java.Lang.Thread+RunnableImplementor.Run () [0x0002b] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    W/ActivityManager( 1502):   at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <01c4ad44191a473f88e7e8b5f5a6f769>:0 
		    W/ActivityManager( 1502):   at (wrapper dynamic-method) System.Object:c66d85c0-2fc5-4ece-a7a6-bc077f553278 (intptr,intptr)
		    D/AndroidRuntime( 2697): Shutting down VM
Comment 1 Bernhard Urban 2017-09-05 16:38:46 UTC
this happens in the `test-runtime` and `test-runtime-aot` step on wrench, e.g.: https://wrench.internalx.com/Wrench/ViewLane.aspx?lane_id=5000&host_id=163&revision_id=910774
Comment 2 Jonathan Pryor 2017-09-05 17:27:23 UTC
The `ObjectDisposedException` is coming from:

https://github.com/xamarin/xamarin-android/blob/5777337/src/Mono.Android/Java.Lang/Thread.cs#L39

which in turn is via this test:

https://github.com/xamarin/xamarin-android/blob/1b3a76c/src/Mono.Android/Test/Android.OS/HandlerTest.cs#L13-L30

(Apologies for the indentation!)

This is presumably a unit test for some bug, but I'm having difficulty finding when that test was added. I will continue hunting.

In the meantime, the test:

1. Creates a HandlerThread and associated Handler instance.
2. Creates a new Java.Lang.Runnable which, when invoked, disposes of itself.
3. Posts the Runnable.Run method to the handler.

(3) will *implicitly* create a `Thread.RunnableImplementor` instance, which invokes the provided delegate, which will be `Runnable.Run`.

We thus have an object graph:

> RunnableImplementor.Handler -> Runnable.Run > Runnable instance

When the Handler executes:

E1. It pulls off the RunnableImplementor instance, calling `RunnableImplementor.Run()`.

E2. `RunnableImplementor.Run()` invokes Handler()

E3. Handler() is `Runnable.Run()`, which *disposes* of the Runnable instance.

E4. `RunnableImplementor.Run()` then unregisters `Handler` from the `RunnalbeImplementor.instances`.

E5. `Dictionary<TKey, TValue>.Remove()` then executes Handler.GetHashCode(), which touches the *now disposed* Handler.Target value, which throws the ObjectDisposedException.

`Delegate.GetHashCode()` should *not* be touching `Delegate.Target`. *That* is the bug.

From some additional searching on Slack, this test *might* be related to:

https://bugzilla.xamarin.com/show_bug.cgi?id=31338#c11
Comment 3 Aleksey Kliger 2017-09-05 17:40:59 UTC
https://github.com/mono/mono/commit/a48bc439850869e565833d7fe6330c289beffe40 change in 2017-06 that started looking at Delegate.Target in GetHashCode ().

(Corresponding master and 2017-08 commit https://github.com/mono/mono/commit/a48bc439850869e565833d7fe6330c289beffe40)

Note that that was a fix for a performance regression on a pathological example.
Comment 4 Jonathan Pryor 2017-09-05 19:11:09 UTC
Regarding the question of "Where did `HandlerTest` come from?", I suspect that I forgot to `git add` the file, and through pure happenstance added that file to the OSS repo.

What luck?

That said, I did find this conversation in Slack:

https://xamarinhq.slack.com/archives/C03CELHQQ/p1440002022008528

> @jonp:
>   Delegate.GetHashCode() is breaking me :wink:
>   https://bugzilla.xamarin.com/show_bug.cgi?id=31338#c11
>   largely because mono’s Delegate.GetHashCode() invokes
>   Delegate.Target.GetHashCode(), while .NET’s doesn’t.
> @kumpera:
>   interesting
>   well, we should import equals/hashcode semantics then
> @mareks:
>   I suggested to switch to reference sources Delegate too but was always rejected
> @jonp:
>   then we should fix Equals() and GetHashCode()?

This was in fact fixed in:

https://github.com/mono/mono/commit/ff17686542746d660b9013920446e95d71dcd294

(...not that the commit message mentions the above conversation in any way, or what bug was being fixed, or...anything else that might be useful...)

The above fix was effectively reverted in:

https://github.com/mono/mono/commit/3acee7af00ae05348ab663e6702d298bd071ce55

This was to fix Bug #58399.
Comment 5 Bernhard Urban 2017-09-05 22:29:58 UTC
https://github.com/mono/mono/pull/5511

once it is merged, I'll take care for the bumping of android.
Comment 6 Bernhard Urban 2017-09-06 12:13:41 UTC
https://github.com/xamarin/xamarin-android/pull/820