Skip to content

Most visited

Recently visited

navigation

View the Java Heap and Memory Allocations with Memory Profiler

The Memory Profiler is a component in the Android Profiler that helps you identify memory leaks and memory churn that can lead to stutter, freezes, and even app crashes. It shows a realtime graph of your app's memory use, lets you capture a heap dump, force garbage collections, and track memory allocations.

To open the Memory Profiler, follow these steps:

  1. Click View > Tool Windows > Android Profiler (you can also click Android Profiler in the toolbar).
  2. Select the device and app process you want to profile from the Android Profiler toolbar. If you've connected a device over USB but don't see it listed, ensure that you have enabled USB debugging.
  3. Click anywhere in the MEMORY timeline to open the Memory Profiler.

Alternatively, you can inspect your app memory from the command line with dumpsys, and also see GC events in logcat.

Why you should profile your app memory

Android provides a managed memory environment—when it 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, it must restart completely.

To help prevent these problems, you should use the Memory Profiler to do the following:

For information about programming practices that can reduce your app's memory use, read Manage Your App's Memory.

Memory Profiler overview

When you first open the Memory Profiler, you'll see a detailed timeline of your app's memory use and access tools to force garbage collection, capture a heap dump, and record memory allocations.

Figure 1. The Memory Profiler

As indicated in figure 1, the default view for the Memory Profiler includes the following:

  1. A button to force a garbage collection event.
  2. A button to capture a heap dump.
  3. A button to record memory allocations.
  4. Buttons to zoom in/out of the timeline.
  5. A button to jump forward to the realtime memory data.
  6. The event timeline, which shows the activity states, user input events, and screen rotation events.
  7. The memory use timeline, which includes the following:
    • A stacked graph of how much memory is being used by each memory category, as indicated by the y-axis on the left and the color key at the top.
    • A dashed line indicates the number of allocated objects, as indicated by the y-axis on the right.
    • An icon for each garbage collection event.

However, not all profiling data is visible by default. If you see a message that says, "Advanced profiling is unavailable for the selected process," you need to enable advanced profiling to see the following:

How memory is counted

The Memory Profiler counts all the private memory pages that your app has committed, according to the Android system. This count does not include pages shared with the system or other apps.

When compared to the previous Android Monitor tool, the new Memory Profiler records your memory use differently, so it might seem like your memory use is now higher. The Memory Profiler monitors some extra categories that increase the total, but if you only care about the Java heap memory, then the "Java" number should be similar to the value from the previous Android Monitor.

And although the Java number probably doesn't exactly match what you saw in Android Monitor, the new number accounts for all physical memory pages that have been allocated to your app's Java heap since it was forked from Zygote. So this provides an accurate representation of how much physical memory your app is actually using.

You might also see unexpected numbers for "Native" memory. Even if you're not using C++ in your app, you'll see native memory usage because the Android framework uses native memory to handle various tasks, such as when handling image assets and other graphics for your app—even though the APIs you use are in Java language.

Currently, the Memory Profiler also shows some false-positive native memory usage in your app that actually belongs to the profiling tools. Roughly 1.5MB of memory is added for ~100k objects—the tools use a map of 64-bit longs to pointers (which should be 4 bytes) per object, plus some hashmap slack. In a future version of the tools, these numbers will be filtered out of your results.

Record memory allocations

While viewing the heap dump is useful to see a snapshot of how much memory is allocated, it doesn't show you how the memory was allocated. For that, you need to record memory allocations. Once you finish a recording session, you can see the following for the recorded duration:

Figure 2. A complete allocation recording, as indicated by the vertical boundaries on the timeline

To view your app's memory allocations, click Record memory allocations in the Memory Profiler toolbar. While it records, interact with your app for as long as necessary to induce memory thrashing or memory leaks. When you're done, click Stop recording (the same button).

The list of allocated objects appears below the timeline, grouped by class name and sorted by their heap count, as shown in figure 2.

To inspect the allocation record, follow these steps:

  1. Browse the list to find objects that have unusually large heap counts and that might be leaked. To help find known classes, click the Class Name column header to sort alphabetically. Then click a class name. The Instance View pane appears on the right, showing each instance of that class, as shown in figure 3.
  2. In the Instance View pane, click an instance. The Call Stack tab appears below, showing where that instance was allocated and in which thread.
  3. In the Call Stack tab, click on any line to jump to that code in the editor.

Figure 3. Details about each allocated object appears in the Instance View on the right

By default, the list is arranged by class name. At the top of the list, you can use the drop-down on the right to switch between the following arrangements:

Capture a heap dump

A heap dump shows which objects your app is using memory at the time you capture the heap dump. Especially after an extended user session, a heap dump can help identify memory leaks by showing you objects still in memory that you believe should no longer be needed. Once you capture a heap dump, you can view the following:

Figure 4.

To capture a heap dump, click Dump Java heap in the Memory Profiler toolbar. 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.

The heap dump appears below the memory timeline, showing all class types in the heap, as shown in figure 4.

To inspect your heap, follow these steps:

  1. Browse the list to find objects that have unusually large heap counts and that might be leaked. To help find known classes, click the Class Name column header to sort alphabetically. Then click a class name. The Instance View pane appears on the right, showing each instance of that class, as shown in figure 5.
  2. In the Instance View pane, click an instance. The References tab appears below, showing every reference to that object.

    Or, click the arrow next to the instance name to view all its fields, and then click a field name to view all its references. And if you want to view the instance details for a field, right-click on the field and select Go to Instance.

  3. In the References tab, if you identify a reference that might be leaking memory, right-click on it and select Go to Instance. This selects the corresponding instance from the heap dump, showing you its own instance data.

By default, the heap dump does not show you the stack trace for each allocated object. To get the stack trace, you must begin recording memory allocations before you click Dump Java heap. If you do, you can then select an instance in the Instance View and see the Call Stack tab alongside the References tab, as shown in figure 5. However, it's likely that some objects were allocated before you began recording allocations, so the call stack is not available for those objects. Instances that include a call stack are indicated with a "stack" badge on the icon .

In your heap dump, look for memory leaks caused by any of the following:

Figure 5. The duration required to capture a heap dump is indicated in the timeline

In the list of classes, you can see the following information:

At the top of the class list, you can use the left drop-down list to switch between the following heap dumps:

By default, the list of objects in the heap are arranged by class name. You can use the other drop-down to switch between the following arrangements:

By default, the list is sorted by the Retained Size column. You can click on any of the column headers to change how the list is sorted.

In the Instance View, each instance includes the following:

Save the heap dump as HPROF

Once you capture a heap dump, the data is viewable in the Memory Profiler only while the profiler is running. When you exit the profiling session, you lose the heap dump. So if you want to save it for review later, export the heap dump to an HPROF file by clicking Export heap dump as HPROF file , in the toolbar below the timeline. In the dialog that appears, be sure to save the file with the .hprof suffix.

You can then reopen the file in Android Studio by dragging the file into an empty editor window (or drop it in the file tab bar).

To use a different HPROF analyzer like jhat, you need to convert the HPROF file from Android format to the Java SE HPROF format. You can do so with the hprof-conv tool provided in the android_sdk/platform-tools/ directory. Run the hprof-conv command with two arguments: the original HPROF file and the location to write the converted HPROF file. For example:

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

Techniques for profiling your memory

While using the Memory Profiler, 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:

Tip: You can also perform the above steps by using the monkeyrunner test framework.

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)