2013-11-15 43 views
1

我使用命令dumpheap -n <PID> <file>創建了本機堆轉儲文件。該文件是可讀的格式,但包含的信息太難理解。我如何分析這個文件並從中獲得有用的信息?Android:如何分析本地堆轉儲?

功能地址是在函數名稱的地方提供的。該映射位於文件的底部。是否有任何工具可以映射它們,併爲函數/庫名稱而不是地址提供有意義的輸出(加載庫/函數的符號)。如果沒有一個,那麼ddms如何做到這一點?還有如何加載符號來顯示函數名稱?

有什麼方法可以比較兩個或多個本機堆轉儲?

轉儲堆文件,我得到這個樣子的

Android原生堆轉儲V1.0

總內存:13863984個 分配記錄:3108

Z 1 SZ 8388608號碼1勝40afcd1a 40afbc0e 40119d30 40795210 407a9bae 407941a0 4076c264 40770b6c 407a47f4 407a481e 40786d44 407a6da6 407a800e 407a58c4 407a820a 40798ac8 40115bb4 4011530c

Z 1 SZ 1516906 NUM 1 BT 40afcd1a 40afbc0e 40119d 30 400658fe 402563d8 5a400b10 5d6c3ed2 5d6c3efc 5d6c3f34 5d69d556 5d6a9de0 40794664 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 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076c264 40770b6c 407a47f4 4078e676 401dd98e 401de472 4005ddd2

Z 1 SZ 262144 NUM 1 BT 40afcd1a 40afbc0e 40119d30 400658fe 40a14416 40a144e0 40a154a4 40a1570e 40a1d8cc 40a20d42 40a1a9e4 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1a A26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076c264 40770b6c 407a47f4 4078e676 401dd98e

Z 1 SZ 65536 NUM 1 BT 40afcd1a 40afbc0e 40119d30 400658fe 40a14400 40a15714 40a1d8cc 40a20d42 40a1a9e4 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076c264 40770b6c 407a47f4 4078e676 401dd98e 401de472 4005ddd2 40119ed4

Z 1 SZ 65536 NUM 1 BT 40afcd1a 40afbc0e 40119d30 400658fe 40a14400 40a15714 40a1d8cc 40a20d42 40a1a9e4 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 40a1aa26 401f0c90 40762e34 40792086 4076c264 40770b6c 407a4aba 407ac010 4076c264 40770b6c 407a47f4 4078e676 401dd98e 401de472 4005ddd2

這些數字表明什麼?

回答

4

數據正在由android_os_Debug.cpp中的dumpNativeHeap()函數生成。每個條目是一個分配記錄,其中包含:

  • 的「受精卵子」標誌:z 0指受精卵過程中(後進行了分配,z 1意味着它發生在受精卵的孩子,即一個應用程序fork())。這對於確定特定分配是否可以通過寫入時複製在多個進程之間共享很有用。
  • 分配的大小,以字節爲單位。
  • 具有完全相同大小和回溯的分配數量。
  • 回溯地址(最多32個)。

如果沒有/proc/<pid>/maps副本來查看哪些二進制文件被映射到了哪裏,那麼這些地址是沒有意義的,因此最終會包含副本。

將二進制+地址轉換爲符號的基本工具是addr2line。您需要從堆棧跟蹤中的地址中減去庫的基址,以獲得庫偏移量。

有一個更簡單的方法。用於生成這些堆轉儲的相同機制也可用於爲DDMS本機堆跟蹤器提供資源。這提供了一個用於瀏覽本地堆內容的完整UI。你可以找到更多關於它的信息herehere

FWIW,這裏是一個例子,它是「艱難的方式」。我甩日曆應用的堆,看到這一行:

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

從地圖條目中的相關線路是:

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)); 
+0

我無法在此處單獨使用行號解碼函數名稱。我應該怎麼做?從DDMS UI我能夠得到它,但是當我從命令行嘗試函數名稱不顯示。我如何解讀底部的地圖? –

+0

你能舉一個你正在嘗試的例子嗎?(即確切的命令行)? – fadden

+0

我使用了這個命令'addr2line -C -f -e /symbols/libexample.so 000c3ed2',其中地址是5d6c3ed2,並且在將高12位清零時,我得到了000c3ed2。我嘗試了DDMS UI和命令行。我點擊了原生堆標籤中的導出數據。在那個allocations.txt文件中,我得到的映射爲5d6c3ed2 /data/data/libexample.so --- Animate():15 ---。但是當我嘗試上面的命令時,我得到了00:?請幫幫我。!!! –

相關問題