Skip to content

ObjectDisposedException caused by GC #2049

@jonathanpeppers

Description

@jonathanpeppers

Steps to Reproduce

  1. Clone Xamarin.Forms: https://github.com/xamarin/Xamarin.Forms.git
  2. Switch to the handle-testing branch: https://github.com/xamarin/Xamarin.Forms/compare/handle-testing
  3. Build Xamarin.Forms.sln, you can open in the IDE and build or nuget restore Xamarin.Forms.sln + msbuild Xamarin.Forms.sln should work
  4. Open .Xamarin.Forms.Android.sln in an IDE and set Xamarin.Forms.ControlGallery.Android as the startup project
  5. Debug the app

After a few screens fly by on the device, you will get a crash on this line: https://github.com/xamarin/Xamarin.Forms/compare/handle-testing#diff-cfe75ccaa32b145fd9a96b49cb931d1dR72

image

android.runtime.JavaProxyThrowable: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Android.Graphics.Bitmap'.
  at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <e8c0e16a54534fa885244f0ad837c79e>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeNonvirtualInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <e8c0e16a54534fa885244f0ad837c79e>:0 
  at Android.Graphics.Bitmap.get_Height () [0x0000a] in <848bbd7c681a4975918c72f17d2f5144>:0 
  at Xamarin.Forms.Platform.Android.ButtonDrawable.Draw (Android.Graphics.Canvas canvas) [0x00021] in D:\agent_work\1\s\Xamarin.Forms.Platform.Android\Renderers\ButtonDrawable.cs:55 
  at Android.Graphics.Drawables.Drawable.n_Draw_Landroid_graphics_Canvas_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_canvas) [0x0000f] in <848bbd7c681a4975918c72f17d2f5144>:0 

While the debugger has paused, this.Handle has recently changed, and _normalBitmap.Handle is inexplicably IntPtr.Zero!

To solve the problem, add an environment.txt to the project with a build action of AndroidEnvironment:

MONO_GC_PARAMS=bridge-implementation=old

Using the old GC implementation, the crash doesn't occur!

Expected Behavior

Although a lot of objects and memory are in use, a crash should not occur here.

Actual Behavior

The app crashes with ObjectDisposedException. I think this issue has plagued various Xamarin.Forms apps (maybe others).

Version Information

I used VS Windows 15.7.6, but this likely will occur with any recent version of Xamarin.Android.

Log File

I enabled GREF logging:

> adb shell setprop debug.mono.log gref,gc

Once the app was running and in a crashed state, I noted _normalBitmap.key_handle is 0xefb562c.

Then I got the log from the device:

> adb shell run-as AndroidControlGallery.AndroidControlGalleryc cat files/.__override__/gref.txt > gref.txt

After several seconds, I could open gref.txt and find 0xefb562c:

handle 0x2f3a; key_handle 0xefb562c: Java Type: `android/graphics/Bitmap`; MCW type: `Android.Graphics.Bitmap`
+g+ grefc 549 gwrefc 0 obj-handle 0x75/I -> new-handle 0x2f2a/G from thread '(null)'(1)
  at Android.Runtime.AndroidObjectReferenceManager.CreateGlobalReference (Java.Interop.JniObjectReference value) [0x00000] in <09e6cd2313ba450ea2148becdafef5de>:0 
  at Java.Interop.JniObjectReference.NewGlobalRef () [0x00000] in <8bda597ae6554278bc49a83870d44290>:0 
  at Android.Runtime.JNIEnv.NewGlobalRef (System.IntPtr jobject) [0x00000] in <09e6cd2313ba450ea2148becdafef5de>:0 
  at Java.Lang.Object.RegisterInstance (Android.Runtime.IJavaObject instance, System.IntPtr value, Android.Runtime.JniHandleOwnership transfer, System.IntPtr& handle) [0x00000] in <09e6cd2313ba450ea2148becdafef5de>:0 
  at Java.Lang.Object.SetHandle (System.IntPtr value, Android.Runtime.JniHandleOwnership transfer) [0x00000] in <09e6cd2313ba450ea2148becdafef5de>:0 
  at Android.Graphics.Canvas..ctor (Android.Graphics.Bitmap bitmap) [0x00000] in <09e6cd2313ba450ea2148becdafef5de>:0 
  at Xamarin.Forms.Platform.Android.ButtonDrawable.CreateBitmap (System.Boolean pressed, System.Int32 width, System.Int32 height) [0x0000e] in C:\Users\jopepper\Desktop\Git\Xamarin.Forms\Xamarin.Forms.Platform.Android\Renderers\ButtonDrawable.cs:164 
  at Xamarin.Forms.Platform.Android.ButtonDrawable.Draw (Android.Graphics.Canvas canvas) [0x0006b] in C:\Users\jopepper\Desktop\Git\Xamarin.Forms\Xamarin.Forms.Platform.Android\Renderers\ButtonDrawable.cs:75 
  at Android.Graphics.Drawables.Drawable.n_Draw_Landroid_graphics_Canvas_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_canvas) [0x00000] in <09e6cd2313ba450ea2148becdafef5de>:0 
  at System.Object.1036a56f-c50a-4b20-ad6d-7ad288fe3c1a (System.IntPtr , System.IntPtr , System.IntPtr ) [0x00000] in <439430c613cf423a807ddc03bf0abc24>:0 

Tracking the handles as GC's occur:

*take_weak obj=0xcfc8be20; handle=0x2f3a
+w+ grefc 591 gwrefc 120 obj-handle 0x2f3a/G -> new-handle 0x92b/W from thread 'finalizer'(15202)

I eventually get to a deadend here:

*try_take_global obj=0xcfc8be20 -> wref=0x92b handle=0x0
-w- grefc 283 gwrefc 390 handle 0x92b/W from thread 'finalizer'(15202)

Which would indicate why _normalBitmap.Handle is IntPtr.Zero.

Full gref log: grefs.zip

Here is the contents of VS debug output window:
debug-output.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: Mono RuntimeMono-related issues: BCL bugs, AOT issues, etc.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions