2011-05-25 17 views

Respuesta

25

Para ampliar la respuesta de CommonsWare:

tengo ni idea de si esto funciona, pero es posible que trate adding a top-level exception handler, y allí asking for a heap dump si es un OutOfMemoryError.

Seguí su sugerencia con éxito en mi propia aplicación para Android con el siguiente código:

public class MyActivity extends Activity { 
    public static class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { 
     @Override 
     public void uncaughtException(Thread thread, Throwable ex) { 
      Log.e("UncaughtException", "Got an uncaught exception: "+ex.toString()); 
      if(ex.getClass().equals(OutOfMemoryError.class)) 
      { 
       try { 
        android.os.Debug.dumpHprofData("/sdcard/dump.hprof"); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
      ex.printStackTrace(); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); 
    } 
} 

Una vez creado el vertedero, es necesario copiarlo desde su teléfono a su PC: Haga clic en "Activar Almacenamiento USB "en el teléfono, encuentre el archivo y cópielo en su disco duro.

Entonces, si desea utilizar el Eclipse Memory Analyzer (MAT) para analizar el archivo, tendrá que convertir el archivo: hprof-conv.exe dump.hprof dump-conv.hprof (hprof-conv está situado bajo android-sdk/tools)

Por último, abra la dump-conv.hprof archivo con MAT

+0

Me he dado cuenta de que esto a menudo funciona, pero a veces no da como resultado un vuelco. No estoy seguro por qué. – emmby

+0

También he hecho lo mismo y, a veces, el archivo de volcado está dañado (o al menos hprof-conv parece pensarlo). Solo agregaría una sugerencia para hacer un System.gc() antes de descargar. – snowdragon

+1

Probablemente la aplicación se terminó antes de que se escribiera el archivo, o (lo que era peor) antes de que finalizara. –

8

Aquí hay una versión mejorada. En la parte superior de la aplicación original de esta aplicación también es compatible con:

  • La captura de errores de memoria insuficiente en todos los temas (no sólo en el hilo principal)
  • La identificación de errores de memoria insuficiente, incluso cuando está oculta en el interior de un error diferente. En algunos casos, el error de falta de memoria se encapsula dentro de un error en tiempo de ejecución.
  • Invocando también el controlador de excepciones no detectadas predeterminado original.
  • Solo funciona en compilaciones DEBUG.

Uso: Llame al método estático initialize en su clase de aplicación en el método onCreate.

package test; 
import java.io.File; 
import java.io.IOException; 
import java.lang.Thread.UncaughtExceptionHandler; 

import android.os.Environment; 
import android.util.Log; 

import com.example.test1.BuildConfig; 

public class OutOfMemoryDumper implements Thread.UncaughtExceptionHandler { 

    private static final String TAG = "OutOfMemoryDumper"; 
    private static final String FILE_PREFIX = "OOM-"; 
    private static final OutOfMemoryDumper instance = new OutOfMemoryDumper(); 

    private UncaughtExceptionHandler oldHandler; 

    /** 
    * Call this method to initialize the OutOfMemoryDumper when your 
    * application is first launched. 
    */ 
    public static void initialize() { 

     // Only works in DEBUG builds 
     if (BuildConfig.DEBUG) { 
      instance.setup(); 
     } 
    } 

    /** 
    * Keep the constructor private to ensure we only have one instance 
    */ 
    private OutOfMemoryDumper() { 
    } 

    private void setup() { 

     // Checking if the dumper isn't already the default handler 
     if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof OutOfMemoryDumper)) { 

      // Keep the old default handler as we are going to use it later 
      oldHandler = Thread.getDefaultUncaughtExceptionHandler(); 

      // Redirect uncaught exceptions to this class 
      Thread.setDefaultUncaughtExceptionHandler(this); 
     } 
     Log.v(TAG, "OutOfMemoryDumper is ready"); 
    } 

    @Override 
    public void uncaughtException(Thread thread, Throwable ex) { 

     Log.e(TAG, "Uncaught exception: " + ex); 
     Log.e(TAG, "Caused by: " + ex.getCause()); 

     // Checking if the exception or the original cause for the exception is 
     // an out of memory error 
     if (ex.getClass().equals(OutOfMemoryError.class) 
       || (ex.getCause() != null && ex.getCause().getClass() 
         .equals(OutOfMemoryError.class))) { 

      // Checking if the external storage is mounted and available 
      if (isExternalStorageWritable()) { 
       try { 

        // Building the path to the new file 
        File f = Environment 
          .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); 

        long time = System.currentTimeMillis(); 

        String dumpPath = f.getAbsolutePath() + "/" + FILE_PREFIX 
          + time + ".hprof"; 

        Log.i(TAG, "Dumping hprof data to: " + dumpPath); 

        android.os.Debug.dumpHprofData(dumpPath); 

       } catch (IOException ioException) { 
        Log.e(TAG,"Failed to dump hprof data. " + ioException.toString()); 
        ioException.printStackTrace(); 
       } 
      } 
     } 

     // Invoking the original default exception handler (if exists) 
     if (oldHandler != null) { 
      Log.v(TAG, "Invoking the original uncaught exception handler"); 
      oldHandler.uncaughtException(thread, ex); 
     } 
    } 

    /** 
    * Checks if external storage is available for read and write 
    * 
    * @return true if the external storage is available 
    */ 
    private boolean isExternalStorageWritable() { 
     String state = Environment.getExternalStorageState(); 
     if (Environment.MEDIA_MOUNTED.equals(state)) { 
      return true; 
     } 
     Log.w(TAG,"The external storage isn't available. hprof data won't be dumped! (state=" + state + ")"); 
     return false; 
    } 
} 
Cuestiones relacionadas