如何在 Android 中获取 Heap Dumps

Heap Dumps 是诊断内存相关问题(如内存泄漏、垃圾收集问题和 java.lang.OutOfMemoryError )的重要工具。它们也是优化内存使用的重要工具。在本文中,我们提供了一些不同的方法来从 Android 应用程序捕获 Heap Dumps。一旦捕获了 Heap Dumps,就可以使用 HeapHero 和 Android Studio’s Heap Analyzer 等强大工具来分析 Heap Dumps。

Memory Profile

下面是在 Android Studio中从 Memory Profile (内存分析器)捕获 Heap Dumps 的步骤:

第一步:运行 app 并选择你要分析的设备。

第二步:在 Android Studio 中点击 View → Tool Windows → Android Profiler。

第三步:在 Android Profiler 中会有一个内存变化的时间轴,这个内存(MEMORY)时间轴位于处理器(CPU)时间轴之下,网络(NETWORK)时间轴之上。双击进入内存时间轴详情,然后就可以点击下载图标进行生成 Heap Dump, 如下图:

生成 Android 的 Heap Dump

第四步:要在系统中存储 Heap Dump,请单击下图中突出显示的图标。

保存 Android 的 Heap Dump 分析文件

第五步:选择一个本地存储文件夹,点击保存即可。

选择本地文件夹保存

ADB

Android Debug Bridge 是一个命令行工具,允许您与设备交互。ADB 提供各种设备操作,例如安装和调试应用程序。它还允许访问 Unix shell,以便在设备上运行各种命令。您可以使用此工具生成 Android Heap Dumps。启动 adb shell 并执行以下步骤:

第一步:识别你的 Android 应用程序的进程 ID.

第一步是确定您的 Android 应用的进程 ID。您可以通过以下命令来实现获取:

adb shell ps | grep <APP-NAME> 

这里需要注意的是如果不能执行,可以先执行 adb shell 切换到 root 用户:

adb shell
su root

adb shell 获取 Android 的进程 ID

上述命令将返回有关进程的详细信息。第二个数字是你的 app 的PID,

创建 Heap Dump

adb shell am dumpheap <PID> <HEAP-DUMP-FILE-PATH>  

PID: Your Android App Process Id
HEAP-DUMP-FILE-PATH: Location where heap dump file should be generated

例如:

adb shell am dumpheap 27306 /data/local/tmp/android.hprof

把文件拉到你的 PC上

以上步骤将在设备中生成 Heap Dump 文件。为了进行分析,您需要将生成的文件拉到您的电脑上。您可以通过发出下面的命令来做到这一点:

adb pull <HEAP-DUMP-FILE-PATH>

HEAP-DUMP-FILE-PATH: Location where heap dump file

例如:

adb pull /data/local/tmp/android.hprof

在 OutOfMemoryError 异常上捕获 Heap Dumps

如果将以下代码放置在应用程序中,则当您的应用程序收到 OutOfMemoryError 时,它将捕获 Heap Dumps。

public class CaptureHeapDumps extends Application {
       private static final String FILE_NAME = "heap-dump.hprof";
       @Override
       public void onCreate() {
          super.onCreate();

Thread.currentThread().setUncaughtExceptionHandler(OutOfMemoryException());

       }
       @NonNull
       private Thread.UncaughtExceptionHandler OutOfMemoryException() {
               return new Thread.UncaughtExceptionHandler() {
               @Override
               public void uncaughtException(Thread t, Throwable e) {
                  String directory = getApplicationInfo().dataDir;
                  String absolutePath = new File(directory, FILE_NAME)
                         .getAbsolutePath();
                  try {
                      Debug.dumpHprofData(absolutePath);
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
               }
        };
    }
}

这将在以下位置生成堆转储文件:/data/user/0/appname/heap-dump.hprof