Android OutOfMemoryErrors don't appear to immediately terminate activity - why?
I'm collecting crash logs from clients via code that runs with the Thread.setDefaultUncaughtExceptionHandler
callback.
Before I wasn't attaching a device ID with my uploads, but now I am, and I'm seeing some very strange reports. Essentially, over the span of 1-2 minutes, I see 50 or so OutOfMemoryError
crash logs all uploaded by the same client, sometimes with two or more logs reported in the same second.
I assume that threads spawned by a parent thread with a setDefaultUncaughtExceptionHandler
are also using the handler, so once the first OutOfMemoryError
happens a cascading effect takes places that touches all application threads at once. Maybe many of these threads are able to upload a crash log before the whole app goes down. However, I would have expected this exception to cause the app to terminate much sooner.
Here's a concrete example -- I see this stack ~10 times in the span of 45sec and sometimes repeatedly within the same second, and I would have expected the first such exception to fully take down the app, not drag it out:
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
at java.lang.Thread.run(Thread.java:1096)
Caused by: java.lang.OutOfMemoryError
at java.lang.AbstractStringBuilder.(AbstractStringBuilder.java:83)
at java.lang.StringBuilder.(StringBuilder.java:68)
at com.appspot.myapp.util.RestClient.convertStreamToString(RestClient.java:306)
at com.appspot.myapp.util.RestClient.executeRequest(RestClient.java:288)
at com.appspot.myapp.util.RestClient.Execute(RestClient.java:185)
at com.appspot.m开发者_如何学运维yapp.GridViewActivity$LoadProfilesTask.doInBackground(GridViewActivity.java:1135)
at com.appspot.myapp.GridViewActivity$LoadProfilesTask.doInBackground(GridViewActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
Can someone explain what happens when Android encounters an OutOfMemoryError
and why I'm seeing this behavior? It's as if the app continues to limp along and is treating these errors as nonfatal...?
Thanks!
Are you replacing the default uncaught exception handler?
If so, does your replacement call something that halts the VM (e.g. System.exit())? Uncaught exceptions don't automatically cause the entire VM to stop.
Fadden,
In my code, I store the default exception handler here:
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
Then, after I have completed uploading the exception info to my server, I call the default exception handler:
defaultUEH.uncaughtException(t, e);
Given these lines here in the code you linked to above:
84 } finally {
85 // Try everything to make sure this process goes away.
86 Process.killProcess(Process.myPid());
87 System.exit(10);
88 }
I am still perplexed as to how my code can continue to run in the face of OutOfMemoryErrors.
精彩评论