Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(XF/Android) Exception occurs when GC collects : "System.ObjectDisposedException: Cannot access a disposed object." #292

Closed
benevbright opened this issue May 9, 2017 · 13 comments

Comments

@benevbright
Copy link

benevbright commented May 9, 2017

Hi Matthew,
Could you look this exception?
When GC collects to make a room (automatically), this exception occurs and app crashes only on XF/Android.

I'm using SKCanvasView at many places.
I found this because the crash report tool received this crash from many users since I released new update SEVERAL DAYS ago. (It's released with SkiaSharp.1.57.0, and before release was on Feb)

skiasharp ver : 1.57.1
XF ver : 2.3.4.231

(UPDATE)
Unfortunately, I tested with 1.56.0 which was included on my Feb release, but the same exception occurs. I guess XF changed how GC handles or other problem.

In my new update, SkCanvas Views are used at many more places, where ListViewCell, ModalPage, CarouselView on Modal, etc.
And Xamarin.Android and I changed even Android SDK since Feb release, so many things are changed.
It's hard to find the reason.

[mono] Unhandled Exception:
[mono] System.ObjectDisposedException: Cannot access a disposed object.
[mono] Object name: 'Android.Graphics.Bitmap'.
[mono]   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00030] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.cs:153 
[mono]   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00002] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:11 
[mono]   at Android.Graphics.Bitmap.Recycle () [0x00000] in /Users/builder/data/lanes/4468/b16fb820/source/monodroid/src/Mono.Android/platforms/android-25/src/generated/Android.Graphics.Bitmap.cs:975 
[mono]   at SkiaSharp.Views.Android.SKCanvasView.FreeBitmap () [0x0000b] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono]   at SkiaSharp.Views.Android.SKCanvasView.Dispose (System.Boolean disposing) [0x00007] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono]   at Java.Lang.Object.Finalize () [0x00051] in /Users/builder/data/lanes/4468/b16fb820/source/xamarin-android/src/Mono.Android/Java.Lang/Object.cs:67 
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.ObjectDisposedException: Cannot access a disposed object.
[mono-rt] Object name: 'Android.Graphics.Bitmap'.
[mono-rt]   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00030] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.cs:153 
[mono-rt]   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00002] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:11 
[mono-rt]   at Android.Graphics.Bitmap.Recycle () [0x00000] in /Users/builder/data/lanes/4468/b16fb820/source/monodroid/src/Mono.Android/platforms/android-25/src/generated/Android.Graphics.Bitmap.cs:975 
[mono-rt]   at SkiaSharp.Views.Android.SKCanvasView.FreeBitmap () [0x0000b] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono-rt]   at SkiaSharp.Views.Android.SKCanvasView.Dispose (System.Boolean disposing) [0x00007] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono-rt]   at Java.Lang.Object.Finalize () [0x00051] in /Users/builder/data/lanes/4468/b16fb820/source/xamarin-android/src/Mono.Android/Java.Lang/Object.cs:67 
@mattleibow
Copy link
Contributor

Hi @benevbright I will look into this. I where the problem starts, my dispose method is trying to release the bitmap - which for some reason is already released. This technically should not happen since after releasing, the bitmap is set to null.

Can you provide more info as to what is causing the issue? Maybe you are scrolling a list view and then this happens? Is it during some page navigation? I need to be able to do some test - it may be that something is happening on another thread, and then the view is being disposed of twice simultaneously.

The finalizer is the result of the GC, but if this view was cleaned up in any way, my field will be null. If the bitmap is being cleaned up somewhere then something is still wrong as I still have my field referencing it. It might be that the GC is collecting both at the same time, which is weird still.

Any further info as what is happening at the time of the crash will be helpful.

@benevbright
Copy link
Author

benevbright commented May 10, 2017

Hi, Matthew.
Thanks for your help.

I made a repro sample project which has a similar layout as my project.
I attach it here.
test_skiasharp_disposedException.zip

The difference between the sample and my project is that it's really hard to reproduce this exception.
To reproduce: try to view the Listview page and modal many time, after that, change the mainpage by using a button as many as you can. I got the exception after I press changing page button about 100 times.
And it's same to reproduce with our app. It occurs when I change my MainPage(when user login/logout). Our app is huge now, so I guess changing MainPage triggers GC to collect.

CLUE : likely it may happen when SkiaCanvas's isVisible property to 'false'.

Tested on Xamarin.Forms 2.3.4.231 / SkiaSharp 1.57.1 / Mac Android Player(Nexus 4) / Android SDK API 25.

But because It's too hard to reproduce, I can not say it's a problem of SkiaSharp.
But It occurs easily on our app than sample project.

[mono] Unhandled Exception:
[mono] System.ObjectDisposedException: Cannot access a disposed object.
[mono] Object name: 'Android.Graphics.Bitmap'.
[mono]   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00030] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.cs:153 
[mono]   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00002] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:11 
[mono]   at Android.Graphics.Bitmap.Recycle () [0x00000] in /Users/builder/data/lanes/4468/b16fb820/source/monodroid/src/Mono.Android/platforms/android-25/src/generated/Android.Graphics.Bitmap.cs:975 
[mono]   at SkiaSharp.Views.Android.SKCanvasView.FreeBitmap () [0x0000b] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono]   at SkiaSharp.Views.Android.SKCanvasView.Dispose (System.Boolean disposing) [0x00007] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono]   at Java.Lang.Object.Finalize () [0x00051] in /Users/builder/data/lanes/4468/b16fb820/source/xamarin-android/src/Mono.Android/Java.Lang/Object.cs:67 
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.ObjectDisposedException: Cannot access a disposed object.
[mono-rt] Object name: 'Android.Graphics.Bitmap'.
[mono-rt]   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00030] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.cs:153 
[mono-rt]   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00002] in /Users/builder/data/lanes/4468/b16fb820/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:11 
[mono-rt]   at Android.Graphics.Bitmap.Recycle () [0x00000] in /Users/builder/data/lanes/4468/b16fb820/source/monodroid/src/Mono.Android/platforms/android-25/src/generated/Android.Graphics.Bitmap.cs:975 
[mono-rt]   at SkiaSharp.Views.Android.SKCanvasView.FreeBitmap () [0x0000b] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono-rt]   at SkiaSharp.Views.Android.SKCanvasView.Dispose (System.Boolean disposing) [0x00007] in <0008caffa6d54ab5af7bddda1c82b23a>:0 
[mono-rt]   at Java.Lang.Object.Finalize () [0x00051] in /Users/builder/data/lanes/4468/b16fb820/source/xamarin-android/src/Mono.Android/Java.Lang/Object.cs:67 

@pauldendulk
Copy link

My users report the same issue.

@Sebastian1989101
Copy link

Sebastian1989101 commented Jun 1, 2017

I have the same issue with Mapsui from pauldendulk which uses SkiaSharp. It looks like this exception comes always when a huge amount of memory is allocated. I got the exception everytime when my app uses a lot of RAM. Even if I navigate away from the Map which is the only usage of SkiaSharp, this exception comes up as soon as I hit about 2.5-3.2GB RAM usage (depends on the amount of background processes). I tried to force the cleanup from the memory at the right moment but it dosn't change a bit.

Edit: This problem only occures on Android. On iOS the app runs fine, so I guess the cleanup works there.

[0:] AppDomain.CurrentDomain.UnhandledException: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Android.Graphics.Bitmap'.
  at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <bd30a18775d94dc8b6263aecd1ca9077>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <bd30a18775d94dc8b6263aecd1ca9077>:0 
  at Android.Graphics.Bitmap.Recycle () [0x0000a] in <d855bac285f44dda8a0d8510b679b1e2>:0 
  at SkiaSharp.Views.Android.SKCanvasView.FreeBitmap () [0x0000b] in <a8778ebdc67a470582197fdb95ec7e8c>:0 
  at SkiaSharp.Views.Android.SKCanvasView.Dispose (System.Boolean disposing) [0x00007] in <a8778ebdc67a470582197fdb95ec7e8c>:0 
  at Java.Lang.Object.Finalize () [0x00048] in <d855bac285f44dda8a0d8510b679b1e2>:0 . IsTerminating: True
In mgmain JNI_OnLoad
06-01 17:18:29.090 E/mono-rt (15355): [ERROR] FATAL UNHANDLED EXCEPTION: System.ObjectDisposedException: Cannot access a disposed object.
06-01 17:18:29.090 E/mono-rt (15355): Object name: 'Android.Graphics.Bitmap'.
06-01 17:18:29.090 E/mono-rt (15355):   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <bd30a18775d94dc8b6263aecd1ca9077>:0 
06-01 17:18:29.090 E/mono-rt (15355):   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <bd30a18775d94dc8b6263aecd1ca9077>:0 
06-01 17:18:29.090 E/mono-rt (15355):   at Android.Graphics.Bitmap.Recycle () [0x0000a] in <d855bac285f44dda8a0d8510b679b1e2>:0 
06-01 17:18:29.090 E/mono-rt (15355):   at **SkiaSharp.Views.Android.SKCanvasView.FreeBitmap** () [0x0000b] in <a8778ebdc67a470582197fdb95ec7e8c>:0 
06-01 17:18:29.090 E/mono-rt (15355):   at **SkiaSharp.Views.Android.SKCanvasView.Dispose** (System.Boolean disposing) [0x00007] in <a8778ebdc67a470582197fdb95ec7e8c>:0 
06-01 17:18:29.090 E/mono-rt (15355):   at Java.Lang.Object.Finalize () [0x00048] in <d855bac285f44dda8a0d8510b679b1e2>:0 

@mattleibow
Copy link
Contributor

Just a note about repro:

I managed to repro the easily by using GC.Collect();
I used the sample app provided by @benevbright, and then added a new button that called the GC. I opened the modal, scrolled, returned to the test5Page and called the GC.

It failed every time after the third collect.

The reason for this is that the finalizer is collecting the bitmap underneath me. When I call Recycle, the handle is zero, thus it throws. I am trying to find a solution - might be to just check the handle before using the bitmap.

@mattleibow
Copy link
Contributor

The new dispose logic is this

if (bitmap != null)
{
    // the GC might have nuked our bitmap :(
    if (bitmap.Handle != IntPtr.Zero && !bitmap.IsRecycled)
        bitmap.Recycle();
    bitmap.Dispose();
    bitmap = null;
}

Although a bit scary, at least the GC is releasing the bitmap :)

@mattleibow mattleibow added this to the 1.58.1 milestone Jun 30, 2017
@mattleibow
Copy link
Contributor

Just pushed out a release that should resolve this: https://github.com/mono/SkiaSharp/releases/tag/v1.58.1

@benevbright
Copy link
Author

benevbright commented Jul 1, 2017

Always thanks, Matthew.
I wish I could have found the code causes the problem.
I will try the update!

@user000000000000001
Copy link

Cool! Thanks a lot!

@Tsukrov
Copy link

Tsukrov commented Aug 19, 2017

Have exactly the same problem in my code.
Have even synchronized it - still getting this totally strange ObjectDisposedException.

@mattleibow
Copy link
Contributor

@Tsukrov Can you provide a stack trace and details about the version of forms, the device and anything else that you may be doing differently?

@mattleibow mattleibow modified the milestones: 1.59.2, 1.58.1 Sep 5, 2017
@mattleibow
Copy link
Contributor

Reopening as this is still an issue. I will investigate this further.

@mattleibow mattleibow reopened this Sep 5, 2017
mattleibow added a commit that referenced this issue Sep 7, 2017
 - we shouldn't be referencing managed objects in the finalizer
@bay0fred
Copy link

bay0fred commented Sep 8, 2017

Hi Matthew,

i encountered a similar problem but with the SKDocument object, more specifically the underlying Stream.
I create a fairly big Pdf document and it seems when the RAM limit is reached and the GC kicks in, it crashes afterwards. I use SkiaSharp version 1.59.1.

09-08 08:45:02.485 D/Mono    ( 3718): Searching for 'sk_document_close'.
09-08 08:45:02.485 D/Mono    ( 3718): Probing 'sk_document_close'.
09-08 08:45:02.485 D/Mono    ( 3718): Found as 'sk_document_close'.
09-08 08:45:02.593 I/art     ( 3718): Starting a blocking GC Explicit
09-08 08:45:02.599 I/art     ( 3718): Explicit concurrent mark sweep GC freed 11000(469KB) AllocSpace objects, 1(40KB) LOS objects, 60% free, 661KB/1685KB, paused 281us total 5.660ms
09-08 08:45:02.599 D/Mono    ( 3718): GC_TAR_BRIDGE bridges 3 objects 6 opaque 0 colors 3 colors-bridged 3 colors-visible 3 xref 0 cache-hit 0 cache-semihit 0 cache-miss 0 setup 0.02ms tarjan 0.01ms scc-setup 0.01ms gather-xref 0.01ms xref-setup 0.01ms cleanup 0.12ms
09-08 08:45:02.599 D/Mono    ( 3718): GC_BRIDGE: Complete, was running for 6.22ms
09-08 08:45:02.599 D/Mono    ( 3718): GC_MINOR: (Nursery full) time 1.59ms, stw 2.59ms promoted 206K major size: 1056K in use: 280K los size: 13312K in use: 10956K
09-08 08:45:02.621 D/Mono    ( 3718): DllImport searching in: 'libSkiaSharp.so' ('libSkiaSharp.so').
09-08 08:45:02.621 D/Mono    ( 3718): Searching for 'sk_paint_delete'.
09-08 08:45:02.621 D/Mono    ( 3718): Probing 'sk_paint_delete'.
09-08 08:45:02.622 D/Mono    ( 3718): Found as 'sk_paint_delete'.
InspectorDebugSession(106): HandleTargetEvent: UnhandledException
Unhandled Exception:

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SKManagedStream: -1736448144'.

I could provide some repro demo project if its desired.

mattleibow added a commit that referenced this issue Sep 12, 2017
 - we shouldn't be referencing managed objects in the finalizer
mattleibow added a commit that referenced this issue Sep 12, 2017
 - we shouldn't be referencing managed objects in the finalizer
mattleibow added a commit that referenced this issue Sep 12, 2017
 - we shouldn't be referencing managed objects in the finalizer
@mattleibow mattleibow modified the milestones: 1.58.1.1, 1.59.2 Sep 12, 2017
mattleibow added a commit that referenced this issue Sep 12, 2017
 - we shouldn't be referencing managed objects in the finalizer
@mattleibow mattleibow removed this from the 1.58.1.1 milestone Oct 25, 2017
@mattleibow mattleibow added this to the 1.59.2 milestone Oct 25, 2017
@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants