2011-05-25 19 views
17

सूर्य JVM एक -XX:+HeapDumpOnOutOfMemoryError विकल्प का समर्थन करता है जब भी जावा प्रक्रिया ढेर से बाहर हो जाती है।क्या एंड्रॉइड प्रक्रिया एक आउटऑफमेमरी एरर पर एक हीप डंप उत्पन्न करने का कोई तरीका है?

क्या एंड्रॉइड पर एक समान विकल्प है जो एक आउटऑफमेमरी अपवाद पर एंड्रॉइड ऐप डंप ढेर करेगा? मैन्युअल रूप से डीडीएमएस का उपयोग करते समय इसे सही तरीके से करने का प्रयास करना मुश्किल हो सकता है।

उत्तर

25

CommonsWare के जवाब उनका विस्तार करने के लिए:

मुझे पता नहीं है कि अगर यह काम करता है, लेकिन आप adding a top-level exception handler कोशिश कर सकते हैं, और वहाँ asking for a heap dump में अगर यह एक OutOfMemoryError है।

मैं निम्नलिखित कोड के साथ अपने ही Android एप्लिकेशन में सफलतापूर्वक अपने सुझाव का पालन किया: चालू करें क्लिक करें ":

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()); 
    } 
} 

बाद डंप बनाया गया है, तो आप अपने पीसी के अपने फोन से इसे कॉपी करने की जरूरत है यूएसबी स्टोरेज "फोन पर, फ़ाइल ढूंढें और इसे अपनी हार्ड ड्राइव पर कॉपी करें। अंत में hprof-conv.exe dump.hprof dump-conv.hprof (HPROF-रूपा android-sdk/tools के नीचे स्थित है)

, dump-conv.hprof खोलें:

उसके बाद, आप ग्रहण मेमोरी विश्लेषक (मेट) का उपयोग करने फ़ाइल का विश्लेषण करना चाहते हैं, तो आप फ़ाइल को गुप्त करने की आवश्यकता होगी MAT

+0

मैंने देखा है कि यह अक्सर काम करता है, लेकिन कभी-कभी इसका परिणाम डंप नहीं होता है। यकीन नहीं है कि क्यों। – emmby

+0

मैंने भी वही किया है और कभी-कभी डंप फ़ाइल दूषित होती है (या कम से कम hprof-conv ऐसा लगता है)। मैं डंपिंग से पहले System.gc() करने के लिए केवल एक सुझाव जोड़ूंगा। – snowdragon

+1

फ़ाइल समाप्त होने से पहले, या (खराब) समाप्त होने से पहले एप्लिकेशन को समाप्त कर दिया गया था। –

8

के साथ फ़ाइल यहां एक बेहतर संस्करण है। मूल कार्यान्वयन के शीर्ष पर इस कार्यान्वयन भी समर्थन करता है:

  • मेमोरी त्रुटियों तब भी जब यह एक अलग त्रुटि के अंदर छिपा हुआ है से बाहर की पहचान करना सभी धागे पर मेमोरी त्रुटियों में से पकड़ने (न केवल मुख्य थ्रेड पर)
  • । कुछ मामलों में आउट ऑफ़ मेमोरी त्रुटि को रनटाइम त्रुटि के अंदर encapsulated है।
  • मूल डिफ़ॉल्ट अनिश्चित अपवाद हैंडलर को भी आमंत्रित करना।
  • केवल डेबग बिल्ड में काम करता है।

उपयोग: onCreate विधि में अपने अनुप्रयोग वर्ग में स्थिर initialize विधि को कॉल करें।

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; 
    } 
} 
संबंधित मुद्दे