Capture a heap dump to see which objects in your app are using up memory at the time of the capture and identify*memory leaks*, or memory allocation behavior that leads to stutter, freezes, and even app crashes. It's especially helpful to take heap dumps after an extended user session, when it could show objects still in memory that should no longer be there.

This page describes the tooling that Android Studio provides to collect and analyze heap dumps. Alternatively, you can inspect your app memory from the command line with[`dumpsys`](https://developer.android.com/studio/command-line/dumpsys)and also[see garbage collection (GC) events in Logcat](https://developer.android.com/studio/debug/logcat).

## Why you should profile your app memory

Android provides a[managed memory environment](https://developer.android.com/topic/performance/memory-overview)---when Android determines that your app is no longer using some objects, the garbage collector releases the unused memory back to the heap. How Android goes about finding unused memory is constantly being improved, but at some point on all Android versions, the system must briefly pause your code. Most of the time, the pauses are imperceivable. However, if your app allocates memory faster than the system can collect it, your app might be delayed while the collector frees enough memory to satisfy your allocations. The delay could cause your app to skip frames and cause visible slowness.

Even if your app doesn't exhibit slowness, if it leaks memory, it can retain that memory even while it's in the background. This behavior can slow the rest of the system's memory performance by forcing unnecessary garbage collection events. Eventually, the system is forced to kill your app process to reclaim the memory. Then when the user returns to your app, the app process must restart completely.

For information about programming practices that can reduce your app's memory use, read[Manage your app's memory](https://developer.android.com/topic/performance/memory).

## Heap dump overview

To capture a heap dump,[select the**Analyze Memory Usage (Heap Dump)**task](https://developer.android.com/studio/profile#start-profiling)(use**Profiler: run 'app' as debuggable (complete data)**) to capture a heap dump. While dumping the heap, the amount of Java memory might increase temporarily. This is normal because the heap dump occurs in the same process as your app and requires some memory to collect the data. After you capture the heap dump, you see the following:
| **Note:** If you need to be more precise about when the dump is created, you can create a heap dump at the critical point in your app code by calling[`dumpHprofData()`](https://developer.android.com/reference/android/os/Debug#dumpHprofData(java.lang.String)).

![](https://developer.android.com/static/studio/images/profiler-heap-dump-view.png)

The list of classes shows the following info:

- **Allocations**: Number of allocations in the heap.
- **Native Size** : Total amount of native memory used by this object type (in bytes). You will see memory here for some objects allocated in Java because Android uses native memory for some framework classes, such as[`Bitmap`](https://developer.android.com/reference/android/graphics/Bitmap).

  | **Note:** The**Native Size**column isn't available for devices running OS versions lower than Android 7.0.
- **Shallow Size**: Total amount of Java memory used by this object type (in bytes).

- **Retained Size**: Total size of memory being retained due to all instances of this class (in bytes).

Use the heap menu to filter to certain heaps:

- **App heap (default)**: The primary heap on which your app allocates memory.
- **Image heap**: The system boot image, containing classes that are preloaded during boot time. Allocations here never move or go away.
- **Zygote heap**: The copy-on-write heap where an app process is forked from in the Android system.

Use the arrangement drop-down to choose how to arrange the allocations:

- **Arrange by class (default)**: Groups all allocations based on class name.
- **Arrange by package**: Groups all allocations based on package name.

Use the class drop-down to filter to groups of classes:

- **All classes (default)**: Shows all classes, including those from libraries and dependencies.
- **Show activity/fragment leaks**: Shows classes that are causing memory leaks.
- **Show project classes**: shows only classes defined by your project.

Click a class name to open the**Instance**pane. Each instance listed includes the following:

- **Depth**: The shortest number of hops from any GC root to the selected instance.
- **Native Size**: Size of this instance in native memory. This column is visible only for Android 7.0 and higher.
- **Shallow Size**: Size of this instance in Java memory.
- **Retained Size** : Size of memory that this instance dominates (as per the[dominator tree](https://en.wikipedia.org/wiki/Dominator_(graph_theory))).

Click an instance to show the**Instance Details** , including its**Fields** and**References** . Common field and reference types are structured types![](https://developer.android.com/static/studio/images/profiler-structured-data-type.png), arrays![](https://developer.android.com/static/studio/images/profiler-array-data-type.png), and primitive data types![](https://developer.android.com/static/studio/images/profiler-primitive-data-type.png)in Java. Right-click on a field or reference to go to the associated instance or line in the source code.

- **Fields**: Shows all the fields in this instance.
- **References** : Shows every reference to the object highlighted in the**Instance**tab.

![](https://developer.android.com/static/studio/images/profiler-heap-dump-instance-details.png)

## Find memory leaks

To quickly filter to classes that might be associated with memory leaks, open the class drop-down and select**Show activity/fragment leaks** . Android Studio shows classes that it thinks indicate memory leaks for[`Activity`](https://developer.android.com/reference/android/app/Activity)and[`Fragment`](https://developer.android.com/reference/android/app/Fragment)instances in your app. The types of data that the filter shows include the following:

- `Activity`instances that have been destroyed but are still being referenced.
- `Fragment`instances that don't have a valid[`FragmentManager`](https://developer.android.com/reference/android/app/FragmentManager)but are still being referenced.

Be aware that the filter might yield false positives in the following situations:

- A`Fragment`is created but has not yet been used.
- A`Fragment`is being cached but not as part of a[`FragmentTransaction`](https://developer.android.com/reference/android/app/FragmentTransaction).

To look for memory leaks more manually, browse the class and instance lists to find objects with large**Retained Size**. Look for memory leaks caused by any of the following:

- Long-lived references to[`Activity`](https://developer.android.com/reference/android/app/Activity),[`Context`](https://developer.android.com/reference/android/content/Context),[`View`](https://developer.android.com/reference/android/view/View),[`Drawable`](https://developer.android.com/reference/android/graphics/drawable/Drawable), and other objects that might hold a reference to the`Activity`or`Context`container.
- Non-static inner classes, such as a[`Runnable`](https://developer.android.com/reference/java/lang/Runnable), that can hold an`Activity`instance.
- Caches that hold objects longer than necessary.

When you find potential memory leaks, use the**Fields** and**References** tabs in**Instance Details**to jump to the instance or source code line of interest.

### Trigger memory leaks for testing

To analyze memory usage, you should stress your app code and try forcing memory leaks. One way to provoke memory leaks in your app is to let it run for a while before inspecting the heap. Leaks might trickle up to the top of the allocations in the heap. However, the smaller the leak, the longer you need to run the app in order to see it.

You can also trigger a memory leak in one of the following ways:

- Rotate the device from portrait to landscape and back again multiple times while in different activity states. Rotating the device can often cause an app to leak an[`Activity`](https://developer.android.com/reference/android/app/Activity),[`Context`](https://developer.android.com/reference/android/content/Context), or[`View`](https://developer.android.com/reference/android/view/View)object because the system recreates the`Activity`, and if your app holds a reference to one of those objects somewhere else, the system can't garbage collect it.
- Switch between your app and another app while in different activity states. For example, navigate to the home screen, then return to your app.

| **Tip:** You can also conduct UI testing using[App Crawler](https://developer.android.com/studio/test/other-testing-tools/app-crawler)or[UI Automator](https://developer.android.com/training/testing/other-components/ui-automator).

## Export and import a heap dump recording

You can[export and import](https://developer.android.com/studio/profile#compare-export-import-traces)a heap dump file from the**Past Recordings** tab in the profiler. Android Studio saves the recording as an`.hprof`file.

Alternatively, to use a different`.hprof`file analyzer like[jhat](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jhat.html), you need to convert the`.hprof`file from Android format to the Java SE`.hprof`file format. To convert the file format, use the`hprof-conv`tool provided in the`{android_sdk}/platform-tools/`directory. Run the`hprof-conv`command with two arguments: the original`.hprof`filename and the location to write the converted`.hprof`file, including the new`.hprof`filename. For example:  

    hprof-conv heap-original.hprof heap-converted.hprof