安卓 : How to analyse the native heap dump?

标签 android memory-leaks android-testing android-debug adb

我已经使用命令 dumpheap -n <PID> <file> 创建了一个 native 堆转储文件.该文件采用人类可读格式,但包含难以理解的信息。我如何分析这个文件并从中获取有用的信息?

函数地址在函数名称的位置提供。该映射在文件底部提供。是否有任何工具可以映射这些并使用函数/库名称而不是地址提供有意义的输出(加载库/函数的符号)。如果没有那么 ddms 是如何做到这一点的?另外如何加载符号以显示函数名称?

有什么方法可以比较两个或多个 native 堆转储?

我得到的转储堆文件是这样的

Android native 堆转储 v1.0

总内存:13863984 分配记录:3108

z 1 sz 8388608 num 1 bt 40afcd1a 40afbc0e 40119d30 40795210 407a9bae 407941a0 4076c264 40770b6c 407a47f4 407a481e 40786d44 40 7a6da6 407a800e 407a58c4 407a820a 40798ac8 40115bb4 4011530c

z 1 sz 1516906 num 1 bt 40afcd1a 40afbc0e 40119d30 400658fe 402563d8 5a400b10 5d6c3ed2 5d6c3efc 5d6c3f34 5d69d556 5d6a9de0 40794 664 407aafa0 4076c264 40770b6c 407a47f4 407a481e 407af4a8 407aff8c 407678b0 40770b6c 407a4aba 407ac010 4076c264 40770b6c 407a47f4 4078e676 401dd98e 401de472 4005ddd2 40119ed4

z 1 sz 262144 num 1 bt 40afcd1a 40afbc0e 40119d30 400658fe 40a14416 40a144e0 40a154a4 40a1570e 40a1d8cc 40a20d42 40a1a9e4 40a1 aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076 c264 40770b6c 407a47f4 4078e676 401dd98e 401de472 4005ddd2

z 1 sz 262144 num 1 bt 40afcd1a 40afbc0e 40119d30 400658fe 40a14416 40a144e0 40a154a4 40a1570e 40a1d8cc 40a20d42 40a1a9e4 40a1 aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 4 07a4aba 407ac010 4076c264 40770b6c 407a47f4 4078e676 401dd98e

z 1 sz 65536 num 1 bt 40afcd1a 40afbc0e 40119d30 400658fe 40a14400 40a15714 40a1d8cc 40a20d42 40a1a9e4 40a1aa26 40a1aa26 40a1a a26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076c264 40770b6c 407a4 7f4 4078e676 401dd98e 401de472 4005ddd2 40119ed4

z 1 sz 65536 num 1 bt 40afcd1a 40afbc0e 40119d30 400658fe 40a14400 40a15714 40a1d8cc 40a20d42 40a1a9e4 40a1aa26 40a1aa26 40a1a a26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076c 264 40770b6c 407a47f4 4078e676 401dd98e 401de472 4005ddd2

这些数字表示什么?

最佳答案

数据由 dumpNativeHeap() 生成在 android_os_Debug.cpp 中发挥作用.每个条目是一个分配记录,其中包含:

  • “zygote child”标志:z 0表示分配是在 zygote 进程中执行的,z 1意味着它发生在 zygote 的 child 中(即 fork() 之后的应用程序进程)。这对于确定是否可以通过写时复制在多个进程之间共享特定分配很有用。
  • 分配的大小,以字节为单位。
  • 具有完全相同大小和回溯的分配数量。
  • 回溯地址(最多 32 个)。

如果没有 /proc/<pid>/maps 的副本,地址就没有意义查看哪些二进制文件被映射到哪里,因此在末尾包含一个副本。

二进制+地址转符号的基本工具是addr2line .您需要从堆栈跟踪中的地址中减去库的基地址以获得库偏移量。

有一个更简单的方法。用于生成这些堆转储的相同机制也可用于提供 DDMS Native Heap Tracker。这提供了用于浏览 native 堆内容的完整 UI。您可以找到更多相关信息 herehere .

FWIW,这是一个“困难的方式”的例子。我转储了日历应用程序的堆并看到了这一行:

z 1  sz    49152  num    1  bt b5aac102 b5aac2f6 b6f8599a b5a5e946 b5a3f268 b6f8d6a0 b6f8b83e

map 条目中的相关行是:

b59ea000-b5a92000 r-xp 00000000 b3:19 817        /system/lib/libdvm.so
b5a9f000-b5ae0000 r-xp 00000000 b3:19 782        /system/lib/libc_malloc_debug_leak.so
b6f78000-b6fbf000 r-xp 00000000 b3:19 780        /system/lib/libc.so

必须从回溯中的地址中减去库的基址。您可以通过查找具有包含回溯地址的地址范围的映射条目来确定它在哪个库中。从左到右(从调用堆栈的顶部到底部)工作:

b5aac102 - b5a9f000 = d102
addr2line -C -f -e [...]/symbols/system/lib/libc_malloc_debug_leak.so d102
--> leak_malloc (malloc_debug_leak.cpp:283)

b5aac2f6...
--> leak_calloc (malloc_debug_leak.cpp:338)

b6f8599a - b6f78000 = d99a
addr2line -C -f -e [...]/symbols/system/lib/libc.so d99a
--> calloc (malloc_debug_common.cpp:231)

b5a5e946 - b59ea000 = 74946
addr2line -C -f -e [...]/symbols/system/lib/libdvm.so 74946
--> compilerThreadStartup (Compiler.cpp:434)

b5a3f268...
--> internalThreadStart(void*) (Thread.cpp:1752)

……等等。此跟踪对应于 dalvik/vm/compiler/Compiler.cpp 中的一行:

pJitTable = (JitEntry*)
            calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));

关于安卓 : How to analyse the native heap dump?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20001153/

相关文章:

Android:更新系统应用

安卓旋转: Why fragment not restored by TAG?

android - MotionLayout 是否支持 fragment 之间的共享元素转换?

java - RabbitMQ QueueingConsumer 可能的内存泄漏

android - uses-permission 权限的单元测试

android - AsyncTask 打开相机

c - C编程内存复制和删除失败

c++ - 如何正确关闭 QWebView 而不会导致内存泄漏?

android-testing - 带有 AsyncTask 的 Espresso

java - 如何告诉 android testrunner 测试 external.apk 而不是生成的 app-debug.apk?