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
)