Quantcast

Re: Crash in Bitmap.Compress()

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Crash in Bitmap.Compress()

Jonathan Pryor
After having debugged a potentially similar issue, it could be caused by a GREF overflow. I've written up some information about it; perhaps it's useful:

        http://mono-android.net/Documentation/Troubleshoot#Unexpected_NullReferenceExceptions
        http://mono-android.net/Documentation/Guides/Android_Debug_Log#Interesting_Messages

 - Jon

On Apr 12, 2011, at 3:15 PM, Dennis Quebe wrote:

> I agree about performance. I don’t know why the event arguments have issues (syncing/threading behind the scenes? Or unmanaged resource issue?). But you will notice that I go through the whole progression. You could just skip that and wrap the whole thing in try/catch. Also, my example is specifically looking for the Accelerometer event.
>  
> From: [hidden email] [mailto:[hidden email]] On Behalf Of Nikolai Sander
> Sent: Tuesday, April 12, 2011 2:14 PM
> To: Discussions related to Mono for Android
> Subject: Re: [mono-android] Crash in Bitmap.Compress()
>  
> Thanks for the tip!
>  
> Although I'm a little concerned about performance. The listener will be called back quite frequently and executing all these try/catch blocks might slow things down significantly... If most problems are solved with checking for NULL I guess it's not a problem.
>  
> Thanks!
> Nikolai
>  
> On Apr 12, 2011, at 12:07 PM, Dennis Quebe wrote:
>
>
> I had the same problem in both Sensor events. I wrapped them in Try/Catch and prefixed it with null validations. There were a lot of consistency issues with when it hit that event if the sensor was set right. For example, OnSensorChanged:
>  
>             if (e == null) { return; } // ENSURE VALID CALL, OTHERWISE EXCEPTION OCCURS
>  
>             if (e.Sensor == null) { return; } // ENSURE VALID CALL, OTHERWISE EXCEPTION OCCURS
>  
>             if (e.Sensor.Type != Android.Hardware.SensorType.Accelerometer) { return; } // ENSURE VALID CALL, OTHERWISE EXCEPTION OCCURS
>  
>  
> Even creating the listener, I wrapped in Try/Catch. I seem to have more sensor issues in the Emulator than when deploying out to a device. I know it seems a little redundant, but it added stability and allowed me to handle the exception.
>  
> -Dennis
>  
>  
> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]] On Behalf Of Nikolai Sander
> Sent: Tuesday, April 12, 2011 2:02 PM
> To: Discussions related to Mono for Android
> Subject: Re: [mono-android] Crash in Bitmap.Compress()
>  
> I narrowed down the problem a bit. At first I wasn't getting any exception in the IDE but now and then the debug log would show me an Null Reference exception in my ISensorEventListener. I read the previous message on here and made sure to derive Java.Lang.Object. My implementation looks like this:
>  
>    class DroidListener : Java.Lang.Object, Android.Hardware.ISensorEventListener
>     {
>  
>         public void OnAccuracyChanged(Sensor sensor, int accuracy)
>         {
>            
>         }
>  
>         public void OnSensorChanged(SensorEvent e)
>         {
>             if (e.Sensor.Type == SensorType.Accelerometer)
>             {
>                                 // Do some stuff
>             }        
>         }
>     }
>  
>         void RegisterGravityListener()
>         {
>             listener = new DroidListener();
>             String service_name = SensorService;
>             SensorManager sensorManager = (SensorManager)GetSystemService(service_name); ;
>             Sensor defSensor = sensorManager.GetDefaultSensor(SensorType.Accelerometer);
>             sensorManager.RegisterListener(listener, defSensor, SensorDelay.Normal);
>         }
>  
> Removing the listener would get rid of the crash in Bitmap.Compress(), so I assume it's a bug with the accelerometer listener.
>  
> I removed it for now in my code, no accelerometer beats crashing on saving images.
>  
> Nikolai
>  
> On Apr 12, 2011, at 9:32 AM, Jonathan Pryor wrote:
>  
> > On Apr 12, 2011, at 3:19 AM, Nikolai Sander wrote:
> >> I'm trying to save a bitmap that I copied from my OpenGL view to disk and after 3-4 successful saves the app crashes.
> >
> > As always, the crash itself would be useful. :-)
> >
> > What does the Android Debug Log contain?
> >
> >             http://mono-android.net/Documentation/Guides/Android_Debug_Log
> >
> > That said, if it's working 3-4 times before crashing the app, I'd suspect a GC leak, though it looks like you are disposing of resources. You might also try calling GC.Collect(0) SavePNG(String) is called and maybe Java.Lang.JavaSystem.Gc() and see if that has any effect.
> >
> > If that fails, please file a bug with a complete, reproducible test case.
> >
> > Thanks,
> > - Jon
> >
> > _______________________________________________
> > Monodroid mailing list
> > [hidden email]
> >
> > UNSUBSCRIBE INFORMATION:
> > http://lists.ximian.com/mailman/listinfo/monodroid
>  
> _______________________________________________
> Monodroid mailing list
> [hidden email]
>  
> UNSUBSCRIBE INFORMATION:
> http://lists.ximian.com/mailman/listinfo/monodroid
> _______________________________________________
> Monodroid mailing list
> [hidden email]
>
> UNSUBSCRIBE INFORMATION:
> http://lists.ximian.com/mailman/listinfo/monodroid
>  
> _______________________________________________
> Monodroid mailing list
> [hidden email]
>
> UNSUBSCRIBE INFORMATION:
> http://lists.ximian.com/mailman/listinfo/monodroid

_______________________________________________
Monodroid mailing list
[hidden email]

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Crash in Bitmap.Compress()

Dennis Quebe

Jon:

 

Those are great articles about GREF. It reminds me of a problem that I had in the previous beta that I am unable to test if it is fixed in the release. I saw a bug about it relating to the Bitmap not releasing unmanaged resources. I had the same problem with BitmapMatrix, in that when I use BitmapMatrix, as a managed object, I expect that it will release the unmanaged resources by calling Dispose in its Finalizer, but I found it did not automatically release or call Dispose when left to the garbage collector. I opened a bug but closed it since it was a day or two later you provided the Release version. Thought I would retest.

 

Either way, I would expect that Bitmap and BitmapMatrix (and any other object that has unmanaged resources) would be the responsible owner for calling Dispose when the Finalizer is called by the garbage collector and I wouldn’t need to litter my code (or worry about resource leaks from forgetting) with Dispose calls.

 

The result was that it would stop the application at about 2000 creation instances in a loop unless I manually called Dispose myself, which it would then continue forever.

 

Thanks.

Dennis Quebe

 

-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Jonathan Pryor
Sent: Thursday, April 14, 2011 9:46 PM
To: Discussions related to Mono for Android
Subject: Re: [mono-android] Crash in Bitmap.Compress()

 

After having debugged a potentially similar issue, it could be caused by a GREF overflow. I've written up some information about it; perhaps it's useful:

 

                http://mono-android.net/Documentation/Troubleshoot#Unexpected_NullReferenceExceptions

                http://mono-android.net/Documentation/Guides/Android_Debug_Log#Interesting_Messages

 

- Jon

 

On Apr 12, 2011, at 3:15 PM, Dennis Quebe wrote:

 

> I agree about performance. I don’t know why the event arguments have issues (syncing/threading behind the scenes? Or unmanaged resource issue?). But you will notice that I go through the whole progression. You could just skip that and wrap the whole thing in try/catch. Also, my example is specifically looking for the Accelerometer event.

> From: [hidden email] [mailto:[hidden email]] On Behalf Of Nikolai Sander

> Sent: Tuesday, April 12, 2011 2:14 PM

> To: Discussions related to Mono for Android

> Subject: Re: [mono-android] Crash in Bitmap.Compress()

> Thanks for the tip!

> Although I'm a little concerned about performance. The listener will be called back quite frequently and executing all these try/catch blocks might slow things down significantly... If most problems are solved with checking for NULL I guess it's not a problem.

> Thanks!

> Nikolai

> On Apr 12, 2011, at 12:07 PM, Dennis Quebe wrote:

>

>

> I had the same problem in both Sensor events. I wrapped them in Try/Catch and prefixed it with null validations. There were a lot of consistency issues with when it hit that event if the sensor was set right. For example, OnSensorChanged:

>             if (e == null) { return; } // ENSURE VALID CALL, OTHERWISE EXCEPTION OCCURS

>             if (e.Sensor == null) { return; } // ENSURE VALID CALL, OTHERWISE EXCEPTION OCCURS

>             if (e.Sensor.Type != Android.Hardware.SensorType.Accelerometer) { return; } // ENSURE VALID CALL, OTHERWISE EXCEPTION OCCURS

> Even creating the listener, I wrapped in Try/Catch. I seem to have more sensor issues in the Emulator than when deploying out to a device. I know it seems a little redundant, but it added stability and allowed me to handle the exception.

> -Dennis

> -----Original Message-----

> From: [hidden email] [mailto:[hidden email]] On Behalf Of Nikolai Sander

> Sent: Tuesday, April 12, 2011 2:02 PM

> To: Discussions related to Mono for Android

> Subject: Re: [mono-android] Crash in Bitmap.Compress()

> I narrowed down the problem a bit. At first I wasn't getting any exception in the IDE but now and then the debug log would show me an Null Reference exception in my ISensorEventListener. I read the previous message on here and made sure to derive Java.Lang.Object. My implementation looks like this:

>    class DroidListener : Java.Lang.Object, Android.Hardware.ISensorEventListener

>     {

>         public void OnAccuracyChanged(Sensor sensor, int accuracy)

>         {

>           

>         }

>         public void OnSensorChanged(SensorEvent e)

>         {

>             if (e.Sensor.Type == SensorType.Accelerometer)

>             {

>                                 // Do some stuff

>             }        

>         }

>     }

>         void RegisterGravityListener()

>         {

>             listener = new DroidListener();

>             String service_name = SensorService;

>             SensorManager sensorManager = (SensorManager)GetSystemService(service_name); ;

>             Sensor defSensor = sensorManager.GetDefaultSensor(SensorType.Accelerometer);

>             sensorManager.RegisterListener(listener, defSensor, SensorDelay.Normal);

>         }

> Removing the listener would get rid of the crash in Bitmap.Compress(), so I assume it's a bug with the accelerometer listener.

> I removed it for now in my code, no accelerometer beats crashing on saving images.

> Nikolai

> On Apr 12, 2011, at 9:32 AM, Jonathan Pryor wrote:

> > On Apr 12, 2011, at 3:19 AM, Nikolai Sander wrote:

> >> I'm trying to save a bitmap that I copied from my OpenGL view to disk and after 3-4 successful saves the app crashes.

> >

> > As always, the crash itself would be useful. :-)

> >

> > What does the Android Debug Log contain?

> >

> >             http://mono-android.net/Documentation/Guides/Android_Debug_Log

> >

> > That said, if it's working 3-4 times before crashing the app, I'd suspect a GC leak, though it looks like you are disposing of resources. You might also try calling GC.Collect(0) SavePNG(String) is called and maybe Java.Lang.JavaSystem.Gc() and see if that has any effect.

> >

> > If that fails, please file a bug with a complete, reproducible test case.

> >

> > Thanks,

> > - Jon

> >

> > _______________________________________________

> > Monodroid mailing list

> > [hidden email]

> >

> > UNSUBSCRIBE INFORMATION:

> > http://lists.ximian.com/mailman/listinfo/monodroid

> _______________________________________________

> Monodroid mailing list

> [hidden email]

> UNSUBSCRIBE INFORMATION:

> http://lists.ximian.com/mailman/listinfo/monodroid

> _______________________________________________

> Monodroid mailing list

> [hidden email]

>

> UNSUBSCRIBE INFORMATION:

> http://lists.ximian.com/mailman/listinfo/monodroid

> _______________________________________________

> Monodroid mailing list

> [hidden email]

>

> UNSUBSCRIBE INFORMATION:

> http://lists.ximian.com/mailman/listinfo/monodroid

 

_______________________________________________

Monodroid mailing list

[hidden email]

 

UNSUBSCRIBE INFORMATION:

http://lists.ximian.com/mailman/listinfo/monodroid


_______________________________________________
Monodroid mailing list
[hidden email]

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Crash in Bitmap.Compress()

Jonathan Pryor
On Apr 15, 2011, at 6:28 PM, Dennis Quebe wrote:
> It reminds me of a problem that I had in the previous beta that I am unable to test if it is fixed in the release. I saw a bug about it relating to the Bitmap not releasing unmanaged resources. I had the same problem with BitmapMatrix, in that when I use BitmapMatrix, as a managed object, I expect that it will release the unmanaged resources by calling Dispose in its Finalizer, but I found it did not automatically release or call Dispose when left to the garbage collector. I opened a bug but closed it since it was a day or two later you provided the Release version. Thought I would retest.

The problem here is twofold:

 1. The GC only knows about memory it allocates, not memory handled by the Dalvik VM or unmanaged memory.
 2. The "proper" mechanism to inform the GC about "memory pressure" is GC.AddMemoryPressure(long), which isn't supported on Mono.

In short, if you allocate lots of "large" objects, where the memory isn't handled by Mono (e.g. large Java-side object graphs, Marshal.AllocHGlobal(), etc.), Mono's GC won't (and can't) know about it, and thus won't know that it should perform collections more frequently. Eventually it'll need to grab more memory from the OS w/o a corresponding full collection, and depending on various factors the process may instead exit (think OOM killer on desktop linux, etc., as -- by default -- desktop linux won't ever return NULL from malloc(3)).

Furthermore, with large Java-side object graphs, it's not easy to tell how big the object graph is (thus complicating the entire idea of calling GC.AddMemoryPressure() in the first place -- what value do you use?).

As a result, it behooves you to keep this in mind, and (if/when appropriate) explicitly dispose of all Java-side objects whenever possible.

 - Jon

_______________________________________________
Monodroid mailing list
[hidden email]

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid
Loading...