graph LR
STRING_IN_UTF8-->xxxx
HEAP_DUMP_SEGMENT-->ROOT_UNKNOWN
HEAP_DUMP_SEGMENT-->ROOT_JNI_GLOBAL
HEAP_DUMP_SEGMENT-->......
HEAP_DUMP_SEGMENT-->CLASS_DUMP
HEAP_DUMP_SEGMENT-->INSTANCE_DUMP
HEAP_DUMP_SEGMENT-->OBJECT_ARRAY_DUMP
HEAP_DUMP_SEGMENT-->PRIMITIVE_ARRAY_DUMP
HEAP_DUMP_END-->xxx
The basic fields in the binary output are u1 (1 byte), u2 (2 byte), u4 (4 byte), and u8 (8 byte). An ID in this implementation is a u4, however the size of an ID is really determined by the “size of identifiers” field in the header.
WARNING: This format is still considered highly experimental, however, all attempts were made to match the format of past HPROF implementations.
The binary output begins with the information:
| [u1]* | An initial NULL terminated series of bytes representing the format name and version, in this implementation and historically, the string “JAVA PROFILE 1.0.1” (18 u1 bytes) followed by a NULL byte. If the TAG “HEAP DUMP SEGMENT” is used this string will be “JAVA PROFILE 1.0.2”. |
|---|---|
| u4 | size of identifiers. Identifiers are used to represent UTF8 strings, objects, stack traces, etc. They can have the same size as host pointers or sizeof(void*), but are not required to be. |
| u4 | high word of number of milliseconds since 0:00 GMT, 1/1/70 |
| u4 | low word of number of milliseconds since 0:00 GMT, 1/1/70 |
Followed by a sequence of records that look like:
| u1 | TAG: denoting the type of the record |
|---|---|
| u4 | TIME: number of microseconds since the time stamp in the header |
| u4 | LENGTH: number of bytes that follow this u4 field and belong to this record |
| [u1]* | BODY: as many bytes as specified in the above u4 field |
The following TAGs are supported:
……
| HEAP DUMP or HEAP DUMP SEGMENT | 0x0C or 0x1C | Contains any number of sub-tags(as body), each begins a u1 field (no order implied here): |
|---|---|---|
| HEAP DUMP END | 0x2C | Terminates a series of HEAP DUMP SEGMENTS. Concatenation of HEAP DUMP SEGMENTS equals a HEAP DUMP. |
| ROOT UNKNOWN | 0xFF | ID object ID |
|---|---|---|
| ROOT JNI GLOBAL | 0x01 | ID object ID ID JNI global ref ID |
| ROOT JNI LOCAL | 0x02 | ID object ID u4 thread serial number u4 frame number in stack trace (-1 for empty) |
| ROOT JAVA FRAME | 0x03 | ID object ID u4 thread serial number u4 frame number in stack trace (-1 for empty) |
| ROOT NATIVE STACK | 0x04 | ID object ID u4 thread serial number |
| ROOT STICKY CLASS | 0x05 | ID object ID |
| ROOT THREAD BLOCK | 0x06 | ID object ID u4 thread serial number |
| ROOT MONITOR USED | 0x07 | ID object ID |
| ROOT THREAD OBJECT | 0x08 | ID thread object ID u4 thread serial number u4 stack trace serial number |
| CLASS DUMP | 0x20 | |
| INSTANCE DUMP | 0x21 | |
| OBJECT ARRAY DUMP | 0x22 | |
| PRIMITIVE ARRAY DUMP | 0x23 |
| ID | class object ID |
|---|---|
| u4 | stack trace serial number |
| ID | super class object ID |
| ID | class loader object ID |
| ID | signers object ID |
| ID | protection domain object ID |
| ID | reserved |
| ID | reserved |
| u4 | instance size (in bytes) |
| u2 | size of constant pool and number of records that follow: u2 constant pool index u1 type of entry: (See Basic Type) value value of entry (u1, u2, u4, or u8 based on type of entry) |
| u2 | Number of static fields: ID static field name string ID u1 type of field: (See Basic Type) value value of entry (u1, u2, u4, or u8 based on type of field) |
| u2 | Number of instance fields (not including super class’s) ID field name string ID u1 type of field: (See Basic Type) |
| ID | object ID |
|---|---|
| u4 | stack trace serial number |
| ID | class object ID |
| u4 | number of bytes that follow |
| [value]* | instance field values (this class, followed by super class, etc) |
| ID | array object ID |
|---|---|
| u4 | stack trace serial number |
| u4 | number of elements |
| ID | array class object ID |
| [ID]* | elements |
| ID | array object ID |
|---|---|
| u4 | stack trace serial number |
| u4 | number of elements |
| u1 | element type (See Basic Type) |
| [u1]* | elements (packed array) |
meaning that heap type have changed
src/main/java/com/android/tools/perflib/heap/HprofParser.java
shark-hprof/src/main/java/shark/Hprof.kt
/**
* Reads the headers of the provided [hprofFile] and returns an opened [Hprof]. Don't forget
* to call [close] once done.
*/
fun open(hprofFile: File): Hprof {
val endOfVersionString = source.indexOf(0)
val versionName = source.readUtf8(endOfVersionString)
// Skip the 0 at the end of the version string.
source.skip(1)
val identifierByteSize = source.readInt()
// heap dump timestamp
val heapDumpTimestamp = source.readLong()
val reader = HprofReader(source, identifierByteSize, byteReadCount)
return Hprof(
channel, source, reader, heapDumpTimestamp, hprofVersion, fileLength
)