Heap Dump: co to je, analýza haldy a odstranění úniků paměti

Autor: IT Sectr Publikováno: 2026-05-07 Doba čtení: 10 min

Heap Dump (dump haldy) — snímek dynamické paměti aplikace obsahující úplné informace o všech živých objektech: jejich třídách, velikostech, vzájemných referencích a dostupnosti od kořenových uzlů (GC roots). Heap Dump je hlavní nástroj analýzy úniků paměti a optimalizace spotřeby zdrojů. Podle Android Developers analýza heap dumpů umožňuje odhalit až 95 % úniků paměti, včetně cyklických referencí, zapomenutých listenerů a neuvolněných statických referencí.

Hlavní body

  • Heap Dump — snímek celé dynamické paměti aplikace s informacemi o každém objektu a referencích mezi nimi.
  • Android Studio Memory Profiler umožňuje zachytávat heap dump v reálném čase pro Java a Kotlin aplikace.
  • Xcode Instruments poskytuje nástroj Allocations pro vytváření a analýzu heap dumpů na iOS/macOS.
  • Shallow a retained size jsou klíčové metriky: shallow — velikost samotného objektu, retained — velikost objektu plus všechny objekty, které drží.
  • Analýza heap dumpu zahrnuje hledání dominator tree, největších retained objects a nejkratších cest ke GC roots.

Co je heap dump a k čemu slouží

Heap dump představuje úplný dump haldy (heap) virtuálního stroje — oblasti paměti, kde jsou umístěny všechny dynamicky vytvářené objekty. V Javě a Kotlinu je to Dalvik/ART na Androidu, ve Swiftu a Objective-C — ARC spravovaná halda na iOS. Heap dump zaznamenává každý objekt, jeho třídu, velikost, pole, reference na jiné objekty a příznaky dosažitelnosti od GC roots (stackové proměnné, statická pole, JNI reference).

Hlavním cílem heap dumpu je odhalování úniků paměti. K úniku dochází, když aplikace nadále drží reference na objekty, které již nejsou potřeba, čímž brání jejich sběru garbage collectorem (nebo uvolnění přes ARC). Typické příčiny: listenery událostí neodhlášené při zničení activity; singly s referencemi na kontext; closures zachycující self; statické kolekce, do kterých se přidávají data bez mazání. Heap dump poskytuje přesný obraz: které objekty jsou „živé", které jsou nadbytečné a kdo na ně přesně referencuje.

Podle údajů Google I/O je více než 60 % hlášení pádů Android aplikací spojeno s OutOfMemoryError a v 80 % případů je hlavní příčinou únik paměti zjistitelný pomocí heap dumpu. U iOS aplikací je situace podobná: úniky způsobené retain cycles jsou jedním z častých důvodů pádů zjistitelných pomocí nástroje Allocations v Xcode.

Kdy je heap dump potřeba

Heap dump by měl být proveden při následujících příznacích: aplikace spotřebovává paměť lineárně při opakovaných akcích (přecházení tam a zpět mezi obrazovkami); po ukončení obrazovky se paměť nevrací na původní úroveň; objevují se OutOfMemoryError nebo varování memory warning na iOS; aplikace je ukončena kvůli překročení limitu paměti (EXC_RESOURCE_RESOURCE na iOS). Pravidelný sběr heap dumpů je součástí protokolu inženýrské kultury ve velkých mobilních projektech, jako jsou Instagram a Spotify.

Heap dump v Android Studio: získání a analýza

Android Studio poskytuje Memory Profiler — vestavěný nástroj pro zachycení heap dumpu v reálném čase. Přístupný přes View → Tool Windows → Profiler. Po spuštění aplikace vyberte relaci, přejděte na kartu Memory a klikněte na Dump Java Heap. Android Studio pozastaví aplikaci, provede dump ART haldy a načte výsledek k analýze. Soubor dumpu má formát .hprof — standard HPROF kompatibilní s většinou analyzátorů paměti.

Po načtení dumpu Android Studio zobrazí tabulku objektů se sloupci: Allocations (počet instancí), Native Size (paměť mimo ART haldu), Shallow Size (paměť samotného objektu), Retained Size (paměť objektu s celým podgrafem). Filtrování podle názvu třídy, řazení podle retained size a vyhledávání podle balíčků umožňuje rychle najít problémové oblasti.

kotlin
// Typický únik — listener neodhlášený v onDestroy
class MainActivity : AppCompatActivity() {
    private val sensorManager by lazy {
        getSystemService(SENSOR_SERVICE) as SensorManager
    }
    private val listener = MySensorListener()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sensorManager.registerListener(listener,
            sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
            SensorManager.SENSOR_DELAY_NORMAL)
    }

    override fun onDestroy() {
        super.onDestroy()
        // ❌ sensorManager.unregisterListener(listener) vynechán
        // → Activity nebude sesbírána GC, heap dump ukáže únik
    }
}

Analýza dominator tree v Android Studio

Karta Dominator Tree zobrazuje objekty, které drží největší množství paměti. Pokud je objekt z dominator tree odstraněn, veškerá paměť, kterou drží, se stane dostupnou pro sběr. To je klíčový nástroj: místo prohlížení tisíců objektů se soustředíte na 10–20, které řídí 80–90 % paměti. Podle Google je analýza dominator tree nejefektivnější způsob, jak najít místo úniku, který zkracuje dobu analýzy z hodin na minuty.

Heap dump v Xcode Instruments: Allocations a Leaks

Xcode Instruments poskytuje dva nástroje pro práci s heap dumpem: Allocations — zachycení dumpu haldy s grafem spotřeby v reálném čase; Leaks — automatické vyhledávání úniků analýzou retain cycles. Allocations zobrazuje všechny objekty na haldě, jejich velikost, počet vytvoření (allocations) a uvolnění (deallocations). Rozdíl mezi počtem vytvoření a uvolnění pro konkrétní třídu ukazuje potenciální únik.

Zachycení heap dumpu v Allocations se provádí tlačítkem Snapshot Memory — nástroj pozastaví aplikaci a provede úplný dump. Poté jsou k dispozici standardní zobrazení: seznam objektů podle tříd, strom volání (call tree) pro každý objekt a generátor zpráv. Na rozdíl od Android Studio Xcode nepoužívá .hprof, ale ukládá data ve vlastním formátu .trace, kompatibilním s Instruments.

swift
// Typický iOS únik — retain cycle přes closure
class NetworkManager {
    var onComplete: ((Data) -> Void)?

    func startRequest() {
        // ❌ Closure zachycuje self — retain cycle
        onComplete = { data in
            self.process(data)
        }
    }
    func process(_ data: Data) {}
}

Nástroj Leaks automaticky detekuje retain cycles a úniky analýzou referenčního grafu. Označuje unikající objekty fialovou ikonou a zobrazuje cestu ke kořeni (GC root). K odstranění retain cycle stačí přidat [weak self] nebo [unowned self] do closure. Pravidelné spouštění nástroje Leaks je povinnou fází CI v týmech používajících Swift pro vývoj iOS.

swift
// Oprava — slabá reference na self
onComplete = { [weak self] data in
    guard let self else { return }
    self.process(data)
}

Shallow size, retained size a dominator tree

Pro správnou analýzu heap dumpu je nutné porozumět třem klíčovým metrikám. Shallow size — objem paměti zabíraný přímo objektem: jeho pole, hlavička (header) a zarovnání. Pro typický Java/Kotlin objekt je shallow size 16–40 bajtů. Retained size — shallow size objektu plus celkový shallow size všech objektů, které jsou dosažitelné pouze přes tento objekt (tj. po jeho odstranění se stanou smetím). Právě retained size ukazuje skutečný vliv objektu na spotřebu paměti.

MetrikaPopisPříklad
Shallow sizeVelikost samotného objektu v bajtechBitmap (100×100) = 40 016 B
Retained sizeShallow size + vše, co držíActivity s View Tree = 2–5 MB
Deep sizeRetained size + vnořené objekty z jiných grafůScrollView s adaptérem = 10–50 MB

Dominator tree — struktura, kde každý objekt odkazuje na svého „dominátora" — objekt, který řídí jeho dosažitelnost. Pokud je dominátor odstraněn, všechny objekty jeho podstromu se stanou smetím. Analýza dominator tree je nejrychlejší způsob, jak najít objekt držící nejvíce paměti. Podle Eclipse MAT (Memory Analyzer Tool) je 90 % úniků odhaleno prohlédnutím top-20 dominator tree během 5 minut.

Analýza úniků paměti pomocí heap dumpu

Proces analýzy úniku pomocí heap dumpu se skládá z několika kroků. Krok 1: proveďte akci, která by měla uvolnit paměť (zavřete obrazovku, dokončete operaci). Krok 2: zavolejte GC (System.gc() v Androidu, vynucený snapshot v Xcode) a udělejte heap dump. Krok 3: najděte objekty, které měly být zničeny (např. instance Activity po finish). Krok 4: pro podezřelý objekt spusťte Path to GC Roots — řetězec referencí, který drží objekt naživu. Poslední reference v řetězci je příčinou úniku.

Cesta ke GC Roots (Path to GC Roots)

Funkce Path to GC Roots je dostupná v Android Studio Profiler, Eclipse MAT a Xcode Instruments. Zobrazuje nejkratší řetězec referencí od GC root k problémovému objektu. Vyloučením slabých (weak) a měkkých (soft) referencí získáte pouze silné (strong) — ty, které skutečně brání sběru. Podle statistik Square Engineering je 70 % úniků v Android aplikacích způsobeno pouze dvěma vzory: statické reference na Activity nebo Context a registrované, ale neodhlášené listenery.

kotlin
// Příklad úniku přes statickou referenci
object AppCache {
    private val cache = mutableMapOf<String, Any>()

    fun storeActivityReference(activity: Activity) {
        cache["current_activity"] = activity // ❌ Únik!
    }
}

// Oprava: slabá reference
object AppCacheFixed {
    private val cache = mutableMapOf<String, WeakReference<Any>>()
}

Porovnání dvou heap dumpů

Technika comparison mode — jedna z nejúčinnějších metod hledání úniků. Udělejte heap dump před a po opakované akci (např. pět přechodů na obrazovku a zpět). Porovnejte počet instancí klíčových tříd: pokud počet Activity vzrostl, ačkoli všechny aktivity byly zavřeny — jedná se o únik. Android Studio a Eclipse MAT podporují automatické porovnávání dumpů se zvýrazněním rozdílů. Podle Google porovnávání dumpů umožňuje najít úniky neviditelné při jednorázové analýze díky akumulaci efektu.

Praktická doporučení pro snížení spotřeby paměti

Na základě analýzy heap dumpů v reálných projektech byly vyvinuty osvědčené postupy optimalizace paměti. Používejte WeakReference pro mezipaměti, zpětná volání a reference na kontext v dlouho žijících objektech. Odhlášujte listenery v onPause/onDestroy pro Android a deinit pro iOS. Vyhýbejte se velkým statickým kolekcím — pokud jsou nezbytné, používejte LruCache s omezením velikosti. Optimalizujte Bitmapy: načítejte obrázky se správným inSampleSize, používejte Glide nebo Picasso s disk cache.

Profilování paměti během vývoje

Zahrňte pravidelné zachycování heap dumpu do CI. Nakonfigurujte úlohu, která spouští instrumentované UI testy, provádí klíčové uživatelské scénáře a porovnává heap dump s baseline. Pokud retained size vzrostl o více než 5 % oproti baseline, sestavení je označeno jako regrese. Tento přístup se praktikuje v Airbnb, Uber a dalších společnostech s vysokými požadavky na kvalitu. Podle Uber Engineering zavedení automatické analýzy heap dumpu v CI snížilo počet chyb souvisejících s pamětí o 70 % za čtvrtletí.

groovy
// Příklad Gradle úlohy pro automatický heap dump v CI
task profileMemory(type: Exec) {
    commandLine 'adb', 'shell',
        'am start -n com.example/.MainActivity'
    // Čekání na načtení
    doLast {
        exec { commandLine 'adb', 'shell',
            'am broadcast -a com.example.DUMP_HEAP' }
    }
}

Často kladené otázky

Jaký je rozdíl mezi shallow size a retained size?

Shallow size — velikost samotného objektu (pole + hlavička). Retained size — velikost objektu plus všech objektů, které se po jeho odstranění stanou smetím. Retained size je hlavní ukazatel vlivu objektu na spotřebu paměti.

Jak udělat heap dump na fyzickém Android zařízení?

Přes Android Studio Profiler vyberte zařízení a proces, klikněte na Dump Java Heap. Alternativně — přes příkazový řádek: adb shell am dumpheap PID /sdcard/dump.hprof, poté adb pull.

Proč může být heap dump obrovský (500 MB+)?

Heap dump zahrnuje všechny živé objekty. Pokud aplikace používá mezipaměti, Bitmapy nebo zpracovává velká data, dump může dosáhnout stovek megabajtů. Filtrujte podle tříd nebo použijte Eclipse MAT pro načtení pouze indexu.

Lze analyzovat heap dump bez Android Studio?

Ano, použijte Eclipse MAT (Memory Analyzer Tool) — bezplatný nástroj pro analýzu .hprof. Podporuje dominator tree, path to GC roots, porovnávání dumpů a automatické vyhledávání úniků pomocí Leak Suspects Report.

Snižuje heap dump výkon aplikace?

Samotný dump — ano, protože vytvoření dumpu pozastaví všechna vlákna (stop-the-world). Bez dumpu — ne. Provádějte dump v kontrolovaných podmínkách (testovací prostředí, CI), ne na produkci.

Shrnutí

  • Heap Dump — úplný snímek haldy aplikace s informacemi o každém objektu a vazbách mezi nimi.
  • Android Studio Memory Profiler a Xcode Instruments Allocations — hlavní nástroje pro zachycení dumpů.
  • Shallow size — velikost samotného objektu; retained size — velikost objektu s celým podgrafem závislostí.
  • Dominator tree — strom dominátorů ukazující objekty řídící nejvíce paměti.
  • Path to GC Roots — řetězec silných referencí bránící objektu ve sběru garbage collectorem.
  • Porovnání dvou heap dumpů (před/po akci) — nejspolehlivější metoda detekce úniků.
  • Automatizace zachycování a analýzy heap dumpů v CI brání paměťovým regresím ve fázi vývoje.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také