Android Hprof 协议解析

1,351 阅读3分钟
原文链接: my.oschina.net

概述

    欲立则先破,想要弄清楚 hprof 是如何记录我们的类,对象所占内存大小,以及引用链等,则先要破解出 hprof 的文件协议及内容。即 hprof 到底写入了什么?

    同其他类型文件,如Bitmap,Hprof 也有自己的文件的协议。其包括了 hprof head 和 hprof body 两部分。head 部分主要包括版本,索引等,而 body 则存储了类,对象,stack trace 等。貌似又是一个套路。

HProf Header

fixed header

主要写入了文件的版本描述及版本号,当前为固定的以'/0'结尾的字串,ID标识的size,写入时间戳。

19 4 8
"JAVA PROFILE 1.0.3/0" indentify size time stamp

string table

写入了当前所用到所有的字符串,包括类名,常量等。这里的TAG,以及其他数据的 TAG 很重要。解析 Hprof 文件协议时,就是用 TAG 来区分的

string 的 TAG 定义为 0x01

1 4 4 4 strlen(string content)
tag time stamp length id string content
tag time stamp length id string content
tag time stamp length id string content
...... ...... ...... ..... ......

class table

class 的 TAG 定义为 0x02

1 4 4 4 4 4 4
tag time stamp length class serial number class object id stack trace serial number

class name string id

...... ..... ..... ..... ...... ...... ......

stack trace

stack trace 的 TAG 定义为 0x05。实际取出来是空,即 num frames 为 0

1 4 4 4 4 4
tag time stamp length serial number thread serial number num frames

HProf Body

Body 部分,以一行为划分,每一行包括所有的 heap dump类型,以及该 heap dump下的子类型

Heap Dump,Heap 级别

1 4 4
tag(0x0C,HEAP_DUMP) time stamp length
tag(0x1C,HEAP_DUMP_SEGMENT) time stamp length

Sub Heap Dump

下面的 string id 对应的 string table 中的 string id

1 4  
0xff(ROOT_UNKNOWN) string id [RootType.UNKNOW]
1 4 4  
0x01(ROOT_JNI_GLOBAL) string id jni global id [RootType.NATIVE_STATIC]
1 4 4 4
0x02(ROOT_JNI_LOCAL) string id thread serial number stack frame number
1 4 4 4
0x03(ROOT_JAVA_FRAME) string id thread serial number stack frame number
1 4 4
0x04(ROOT_NATIVE_STACK) string id thread serial number
1 4  
0x05(ROOT_STICKY_CLASS) string id [RootType.SYSTEM_CLASS]
1 4 4
0x06(ROOT_THREAD_BLOCK) string id thread serial number
1 4  
0x07(ROOT_MONITOR_USED) string id [RootType.BUSY_MONITOR]
1 4 4 4
0x08(ROOT_THREAD_OBJECT) string id thread serial number stack frame number
1 4  
0x20(ROOT_CLASS_DUMP) string id 有点复杂,在下面单独列出来
1 4 4 4 4
0x21(ROOT_INSTANCE_DUMP) string id stack id class id remaining(skip)
1 4 4 4 4  
0x22(ROOT_OBJECT_ARRAY_DUMP) string id stack id num elements class id 4 * num elements(skip)
1 4 4 4 1  
0x23(ROOT_PRIMITIVE_ARRAY_DUMP) string id stack id num elements primitive type 4 * num elements(skip)
1  
0xc3(ROOT_PRIMITIVE_ARRAY_NODATA) 暂时表示错误类型
1 4 4
0xfe(ROOT_HEAP_DUMP_INFO) heap id heap name id(string id)
1 4  
0x89(ROOT_INTERNED_STRING) string id [RootType.INTERNED_STRING]
1 4  
0x8a(ROOT_FINALIZING) string id [RootType.FINALIZING]
1 4  
0x8b(ROOT_DEBUGGER) string id [RootType.DEBUGGER]
1 4  
0x8c(ROOT_REFERENCE_CLEANUP) string id [RootType.REFERENCE_CLEANUP]
1 4  
0x8d(ROOT_VM_INTERNAL) string id [RootType.VM_INTERNAL]
1 4 4 4
0x8e(ROOT_JNI_MONITOR) string id thread serial number stack frame number
1 4  
0x90(ROOT_UNREACHABLE) string id [RootType.UNREACHABLE]

0x20(ROOT_CLASS_DUMP)

0x20(ROOT_CLASS_DUMP) 1
id 4
stack serial number 4
super class id 4
class loader id 4
signeres id 4
protection domain id 4
reserved 4
reserved 4
instance size 4
const pool num entries 2
2 * num entries  
static fields num entries 2
static fields static fields num entries * (static fields),下面会再单独列出来
instance fields num entries 2
instance fields instance fields num entries * (instance fields)

0x20(ROOT_CLASS_DUMP).Static Fields

4 1 4
static fields id static fields type type size

0x20(ROOT_CLASS_DUMP).Instance Fields

4 1
instance id instance type