Sobes.tech
Middle+

Jak určit přítomnost úniku paměti při analýze dumpu?

sobes.tech AI

Odpověď od AI

Pro detekci paměťových úniků v dumpu (soubor HPROF) se používají nástroje, které analyzují graf objektů na haldě. Hlavní kroky:

  1. Získání dumpu paměti:

    • Pomocí Memory Profiler v Android Studio.
    • Příkazem adb shell dumpheap <název_balíčku> /data/local/tmp/dump.hprof.
    • Voláním systému Debug.dumpHprofData(filePath).
  2. Analýza dumpu:

    • Otevření dumpu v Android Studio: v Memory Profiler nebo přes menu "File" -> "Open".
    • Analýza objektů: seřaďte objekty podle velikosti (Shallow Size, Retained Size) a počtu.
    • Hledání podezřelých objektů: hledejte třídy, které by měly být zničeny (například Activity, Fragment, Contexts), ale mají velké množství instancí nebo významnou Retained Size.
    • Studium cesty k objektu (Reference Chain): vyberte podezřelý objekt a sledujte jeho cestu k objektům kořenům (GC roots). To ukáže, kdo drží odkaz, čímž zabrání sběru odpadu.
    • Hledání statických odkazů: statická pole jsou často zdrojem úniků, pokud uchovávají dlouhodobé odkazy na kontexty nebo pohledy.
    • Použití LeakCanary: knihovna automatizuje detekci, dump a analýzu úniků v reálném čase, poskytujíc podrobný popis cesty úniku.
  3. Interpretace výsledků:

    • Dlouhá cesta k GC root, obsahující odkazy na objekty, které by měly být zničeny, naznačuje problém.
    • Odkazy z statických polí, AsyncTasků, Handlerů s zpožděním, nesprávně odregistrovaných listenerů/callbacků nebo singletonů v aktivitách či pohledech jsou často příčinou úniků.

Příklad analýzy cesty k GC root v Android Studio Memory Profiler:

// Příklad cesty k GC root, která ukazuje na únik
// android.app.Activity instance s mDestroyed=true
//   reference na android.widget.LinearLayout
//     reference na android.view.View $ListenerInfo
//       reference na com.example.MyActivity$1 (anonimní třída implementující View.OnClickListener)
//         reference na com.example.MyActivity (odkaz způsobující únik)

V tomto příkladu udržuje anonymní třída (posluchač kliknutí na tlačítko) implicitní odkaz na MyActivity, i když by aktivita již měla být zničena (mDestroyed=true). Tento posluchač je patrně zaregistrován nebo udržován jiným dlouhodobým objektem (například statickým polem nebo singletonem).