概述
欲立则先破,想要弄清楚 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 |