/* * Catch out-of-memory errors with an Thread.UncaughtExceptionHandler * and generate an hprof heap dump. */ import android.os.Debug; import java.io.IOException; import java.util.ArrayList; public class HeapDump { public static void test() { Catcher catcher = new Catcher(); catcher.setAsDefaultHandler(); runOutOfMemory(); } static void runOutOfMemory() { ArrayList al = new ArrayList(); while (true) { al.add(new byte[1024*1024]); } } } class Catcher implements Thread.UncaughtExceptionHandler { Thread.UncaughtExceptionHandler mPrevHandler; public void setAsDefaultHandler() { Thread.UncaughtExceptionHandler oldHandler = Thread.getDefaultUncaughtExceptionHandler(); if (oldHandler != null && mPrevHandler == oldHandler) { throw new RuntimeException("don't call this twice"); } mPrevHandler = oldHandler; Thread.setDefaultUncaughtExceptionHandler(this); } public void uncaughtException(Thread t, Throwable e) { System.out.println("caught! " + e); if (e instanceof OutOfMemoryError) { // App requires WRITE_EXTERNAL_STORAGE permission to // write to /sdcard. Could also write to the app-private // data area. try { Debug.dumpHprofData("/sdcard/dump.hprof"); } catch (IOException ioe) { System.err.println("hprof dump failed"); } } if (mPrevHandler != null) { System.out.println("calling previous handler"); mPrevHandler.uncaughtException(t, e); } // In an Android app, the system crash-catcher will kill the // app after asking the system to display the "force close" // dialog, so we shouldn't get here. If you remove the // mPrevHandler call, it would be wise to exit() here. } }