Sobes.tech
Middle+

Cum se determină prezența unei scurgeri de memorie la analiza unui dump?

sobes.tech AI

Răspuns de la AI

Pentru detectarea scurgerilor de memorie într-un dump (fișier HPROF), se folosesc instrumente care analizează graficul obiectelor din heap. Pașii principali:

  1. Obțineți dump-ul de memorie:

    • Prin Memory Profiler din Android Studio.
    • Cu comanda adb shell dumpheap <numele_pachetului> /data/local/tmp/dump.hprof.
    • Prin apelul de sistem Debug.dumpHprofData(filePath).
  2. Analizați dump-ul:

    • Deschideți dump-ul în Android Studio: în Memory Profiler sau prin meniul "File" -> "Open".
    • Analizați obiectele: sortați obiectele după dimensiune (Shallow Size, Retained Size) și numărul de instanțe.
    • Căutați obiecte suspecte: căutați clase care trebuie distruse (de exemplu, Activity, Fragment, Contexts), dar au multe instanțe sau un Retained Size semnificativ.
    • Studiați drumul către obiect (Reference Chain): selectați un obiect suspect și urmăriți drumul său către obiectele rădăcină (GC roots). Acest lucru va arăta cine menține referința, prevenind colectarea gunoiului.
    • Căutați referințe statice: câmpurile statice sunt adesea o sursă de scurgeri dacă păstrează referințe de lungă durată la contexte sau vizualizări.
    • Utilizați LeakCanary: biblioteca automatizează detectarea, dump-ul și analiza scurgerilor în timp real, oferind o descriere detaliată a drumului scurgerii.
  3. Interpretarea rezultatelor:

    • Un drum lung către GC root, conținând referințe la obiecte care trebuie distruse, indică o problemă.
    • Referințele din câmpuri statice, AsyncTask, Handler-e cu întârzieri, listeners/callbacks ne-dezabonate corect sau singleton-uri în activități sau vizualizări sunt adesea cauza scurgerilor.

Exemplu de analiză a drumului către GC root în Android Studio Memory Profiler:

// Exemplu de drum către GC root care indică o scurgere
// android.app.Activity instanță cu mDestroyed=true
//   referință la android.widget.LinearLayout
//     referință la android.view.View $ListenerInfo
//       referință la com.example.MyActivity$1 (clasă anonimă care implementează View.OnClickListener)
//         referință la com.example.MyActivity (referință care cauzează scurgerea)

În acest exemplu, o clasă anonimă (ascultător de clic pe buton) menține o referință implicită la MyActivity, deși activitatea ar trebui să fie deja distrusă (mDestroyed=true). Acest ascultător pare să fie înregistrat sau reținut de un alt obiect de lungă durată (de exemplu, un câmp static sau un singleton).