android.media.MediaPlayer.native_finalize timed out after 10 seconds

print
MediaPlayer.java
android.media.MediaPlayer.native_finalize
Heads Up!

.finalize() timed out after 10 seconds
Details:
This is an Android system-level crash that happened because JVM garbage collection took too long. It was likely caused by an incorrect clean-up of native resources, or because garbage collection occurred while your app was backgrounded. Although this crash cannot be avoided, you can mitigate its effects. For more details, check out the first resource.

 

https://stackoverflow.com/questions/24021609/how-to-handle-java-util-concurrent-timeoutexception-android-os-binderproxy-fin

Full disclosure – I’m the author of the previously mentioned talk in TLV DroidCon.

I had a chance to examine this issue across many Android applications, and discuss it with other developers who encountered it – and we all got to the same point: this issue cannot be avoided, only minimized.

I took a closer look at the default implementation of the Android Garbage collector code, to understand better why this exception is Thrown and on what could be the possible causes. I even found a possible root cause during experimentation.

The root of the problem is at the point a device “Goes to Sleep” for a while – this means that the OS has decided to lower the battery consumption by stopping most User Land processes for a while, and turning Screen off, reducing CPU cycles, etc. The way this is done – is on a Linux system level where the processes are Paused mid run. This can happen at any time during normal Application execution, but it will stop at at a Native system call, as the context switching is done on the kernel level. So – this is where the Dalvik GC joins the story. The Dalvik GC code (as implemented in the Dalvik project in the AOSP site) is not a complicated piece of code. The basic way it work is covered in my DroidCon slides. what I did not cover is the basic GC loop – at the point where the collector has a list of Objects to finalize (and destroy). the loop logic at the base can be simplified like this:

  1. take starting_timestamp,
  2. remove object for list of objects to release,
  3. release object – finalize() and call native destroy() if required,
  4. take end_timestamp,
  5. calculate (end_timestamp - starting_timestamp) and compare against a hard coded timeout value of 10 seconds,
  6. if timeout has reached – throw the concurrent.TimeoutException and kill the process.

Now consider the following scenario:

Application runs along doing its thing. this is not a User facing application, it runs in the background. During this background operation, Objects are created, used and need to be collected to release memory. Application does not bother with a Wakelock – as this will affect the battery adversely, and seems unnecessary. this means the Application will invoke the GC from time to time. Normally the GC runs is completed without a hitch. Sometimes (very rarely) the System will decide to Sleep in the middle of the GC run. This will happen if you run your application long enough, and monitor the Dalvik memory logs closely. Now – consider the timestamp logic of the basic GC loop – it is possible for the device to start the run, take a start_stamp, and go to sleep at the destroy() native call on a system object. when it wakes up and resumes the run, the destroy() will finish, and the next end_stamp will be the time it took the destroy() call+the sleep time. If the sleep time was long – over 10 seconds, the concurrent.timeout exception will be thrown.

I have seen this in the graphs generated from the analysis python script – for Android System Applications, not just my own monitored apps. collect enough logs, you will eventually see it.

Bottom line:

The issue cannot be avoided – you will encounter it if your app runs in the background. You can mitigate by taking a wakelock, and prevent the device from sleeping, but that is a different story altogether, and a new headache, and maybe another talk in another con.

You can minimize the problem by reducing GC calls – making the scenario less likely. tips are in the slides.

I have not yet had the chance to go over the Dalvik 2 (a.k.a ART) GC code – which boasts a new Generational Compacting feature, or performed any experiments on an Android Lollipop.

Added 7/5/2015:

After reviewing the Crash reports aggregation for this crash type, it looks like these crashes from version 5.0+ of Android OS (Lollipop with ART) only account for .5% of this crash type. This means that the ART GC changes has reduced the frequency of these crashes.

Added 6/1/2016:

Looks like the Android project has added a lot of info on how the GC works in Dalvik 2.0 (a.k.a ART). You can read about it here – Debugging ART Garbage Collection . It also discusses some tools to get information on the GC behavior for your app. Sending a SIGQUIT to your app process will essentially cause an ANR, and dump the application state to a log file for analysis.

shareimprove this answer
In my case, I’m also planning to try to mitigate this by finding ways to reduce the amount of code/time I’m running in the background. Thanks for your research on the topic. – parkerfath Mar 12 ’15 at 23:36
removing any background processing done in your app will greatly help reduce the problem. – oba Apr 30 ’15 at 7:03
For what it is worth, this happens still in Marshmallow (6.0.1). That said, I have only ever received this error once. So it doesn’t seem to be a gigantic problem. Thank you for your thorough explanation. – Knossos Jan 13 ’16 at 6:09
After some time, I got the distinct impression that fixing this problem in the OS is very problematic, and requires cooperation between Google and the OEMs. I do not expect this to be fixed any time soon. – oba Jan 13 ’16 at 9:16
I’m using wakelock but still encountered this issue on Android 4.4.2. My app has some background operations but mainly designed to work all day long while charge cable mounted. Is there any different way to mitigate this issue? – MiloRambaldi Feb 16 ’16 at 8:08

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.