Experimental HPROF heap dump parser for MoonBit.
moon update
moon check --target wasm --deny-warn
moon build --target wasm --deny-warn
moon test --target wasm --deny-warn
moon run cmd/main --target wasm -- --help
moon run cmd/main --target wasm -- summary path/to/heap.hprof
moon run cmd/main --target wasm -- histogram path/to/heap.hprof --format csv --limit 20
moon run cmd/main --target wasm -- objects path/to/heap.hprof 0 --limit 10
moon run cmd/main --target wasm -- check path/to/heap.hprof| 能力 | API / 命令 |
|---|---|
| 索引与汇总 | parse、parse_with_limits、summary |
| 类、继承和静态字段 | class_info、hierarchy、static_fields、class |
| 对象查找与字段解码 | object_ids、instance_fields、field、objects、object |
| 数组分页 | array_values,支持八种基本类型及对象引用数组 |
| Java String | java_string,支持 char[]、Latin-1、compact UTF-16,字节顺序由调用者明确指定 |
| 根引用与栈 | roots、roots_for、stack_trace、roots / stack 命令 |
| 根可达性与支配分析 | gc_analysis API;CLI gc 输出可达对象、立即支配者和 retained payload |
| GC Root 路径 | GCAnalysis::root_path;CLI root-path <object-id> 输出最短强引用路径 |
| 直接引用 | references / refs,返回字段或数组引用,不进行可达性或泄漏推断 |
| 反向引用与路径 | ReferenceIndex、incoming、referrer_ids、most_referenced、有预算的 path;CLI inbound / referenced |
| 内容预览与批量导出 | preview、objects_jsonl、previews_jsonl;CLI preview / export |
| 统计与比较 | histogram、select_histogram、totals、largest_objects、loader_statistics、compare_heaps |
| 导出 | JSON、RFC 4180 CSV;diff 比较两份转储 |
| 校验 | validate / check,检查继承链、字段布局和元数据引用 |
moon run cmd/main --target wasm -- summary heap.hprof --class java/lang/String
moon run cmd/main --target wasm -- histogram heap.hprof --prefix java/ --sort payload --format json
moon run cmd/main --target wasm -- object heap.hprof 0x1234 --offset 0 --limit 20
moon run cmd/main --target wasm -- diff before.hprof after.hprof
moon run cmd/main --target wasm -- inbound heap.hprof 0x1234 --limit 20
moon run cmd/main --target wasm -- preview heap.hprof 0x1234 --limit 8
moon run cmd/main --target wasm -- export heap.hprof 0 --limit 100 > objects.jsonl
moon run cmd/main --target wasm -- gc heap.hprof --limit 20
moon run cmd/main --target wasm -- root-path heap.hprof 0x1234./validation/verify.ps1 -Jdk '你的JDK安装目录'pub struct ClassInfo {
id : UInt64
stack_serial : UInt64
superclass_id : UInt64
loader_id : UInt64
signers_id : UInt64
protection_domain_id : UInt64
instance_size : Int
constants : Array[ConstantEntry]
statics : Array[StaticField]
fields : Array[FieldSpec]
}pub struct HeapTotals {
class_objects : Int
instance_objects : Int
array_objects : Int
payload_bytes : Int64
array_elements : Int64
largest_payload_id : UInt64
largest_payload_bytes : Int
}pub struct HistogramDelta {
name : String
kind : String
before_count : Int
after_count : Int
count_delta : Int64
payload_delta : Int64
}pub struct HistogramRow {
name : String
class_id : UInt64
loader_id : UInt64
kind : String
count : Int
payload_bytes : Int64
elements : Int64
}pub struct LoaderStatistics {
loader_id : UInt64
class_count : Int
instance_count : Int
array_count : Int
payload_bytes : Int64
}pub struct ObjectInfo {
id : UInt64
kind : ObjectKind
class_id : UInt64
stack_serial : UInt64
primitive_kind : Int
length : Int
payload_offset : Int
payload_bytes : Int
}pub struct ObjectPreview {
id : UInt64
kind : String
class_name : String
payload_bytes : Int
array_length : Int?
text : String
truncated : Bool
}pub struct ParseLimits {
max_file_bytes : Int
max_objects : Int
max_classes : Int
max_strings : Int
max_text_bytes : Int
max_roots : Int
max_records : Int
max_trace_frames : Int
}fn ParseLimits::new(max_file_bytes? : Int, max_objects? : Int, max_classes? : Int, max_strings? : Int, max_text_bytes? : Int, max_roots? : Int, max_records? : Int, max_trace_frames? : Int) -> ParseLimits raise ParseErrorpub struct ReferenceEdge {
source_id : UInt64
target_id : UInt64
label : String
}pub struct ReferenceIndex {
// private fields
}fn ReferenceIndex::build(heap : Summary, max_edges? : Int, max_slots? : Int) -> ReferenceIndex raise ParseErrorfn ReferenceIndex::incoming(self : ReferenceIndex, id : UInt64, offset? : Int, limit? : Int) -> Array[ReferenceEdge] raise ParseErrorfn ReferenceIndex::most_referenced(self : ReferenceIndex, limit? : Int) -> Array[ReferencedObject] raise ParseErrorfn ReferenceIndex::outgoing(self : ReferenceIndex, id : UInt64, offset? : Int, limit? : Int) -> Array[ReferenceEdge] raise ParseErrorfn ReferenceIndex::path(self : ReferenceIndex, source : UInt64, target : UInt64, max_depth? : Int, max_nodes? : Int, max_edges? : Int) -> ReferencePath raise ParseErrorfn ReferenceIndex::referrer_ids(self : ReferenceIndex, id : UInt64, offset? : Int, limit? : Int) -> Array[UInt64] raise ParseErrorpub struct ReferencePath {
found : Bool
truncated : Bool
visited_nodes : Int
inspected_edges : Int
edges : Array[ReferenceEdge]
}pub struct ReferencedObject {
object_id : UInt64
reference_count : Int
source_count : Int
present_in_heap : Bool
}pub struct ResolvedFrame {
id : UInt64
class_name : String
method_name : String
signature : String
source_name : String
line_number : Int
}pub struct RootInfo {
tag : Int
object_id : UInt64
related_id : UInt64
thread_serial : UInt64
frame_number : UInt64
}pub struct StackFrame {
id : UInt64
method_name_id : UInt64
signature_id : UInt64
source_name_id : UInt64
class_serial : UInt64
line_number : Int
}pub struct Summary {
id_size : Int
classes : Int
instances : Int
object_arrays : Int
primitive_arrays : Int
timestamp_ms : UInt64
// private fields
}fn Summary::array_values(self : Summary, id : UInt64, offset? : Int, limit? : Int) -> Array[Value] raise ParseErrorfn Summary::field(self : Summary, id : UInt64, name : String, declaring_class? : UInt64) -> Value? raise ParseErrorfn Summary::gc_analysis(self : Summary, max_edges? : Int, max_slots? : Int) -> GCAnalysis raise ParseErrorfn Summary::java_string(self : Summary, id : UInt64, utf16_little_endian~ : Bool, max_chars? : Int) -> String raise ParseErrorfn Summary::object_ids(self : Summary, class_id? : UInt64, offset? : Int, limit? : Int) -> Array[UInt64] raise ParseErrorfn Summary::object_json(self : Summary, id : UInt64, offset? : Int, limit? : Int) -> Json raise ParseErrorfn Summary::objects_jsonl(self : Summary, class_id? : UInt64, offset? : Int, limit? : Int, array_limit? : Int) -> String raise ParseErrorfn Summary::payload(self : Summary, id : UInt64, offset? : Int, limit? : Int) -> Bytes raise ParseErrorfn Summary::preview(self : Summary, id : UInt64, max_items? : Int, max_chars? : Int) -> ObjectPreview raise ParseErrorfn Summary::previews_jsonl(self : Summary, class_id? : UInt64, offset? : Int, limit? : Int, max_items? : Int, max_chars? : Int) -> String raise ParseErrorfn Summary::references(self : Summary, id : UInt64, limit? : Int) -> Array[ReferenceEdge] raise ParseErrorfn Summary::select_histogram(self : Summary, prefix? : String, kind? : String, sort? : HistogramSort, offset? : Int, limit? : Int) -> Array[HistogramRow] raise ParseErrorpub struct ThreadInfo {
serial : UInt64
object_id : UInt64
stack_serial : UInt64
name_id : UInt64
group_name_id : UInt64
parent_group_name_id : UInt64
}pub enum Value {
Reference(UInt64)
Boolean(Bool)
Character(Int)
ByteValue(Int)
ShortValue(Int)
IntValue(Int)
LongValue(Int64)
FloatValue(Double)
DoubleValue(Double)
} derive(Debug)fn csv_cell(value : String) -> Stringfn display_class_name(name : String) -> Stringfn encode_hprof_text(text : String) -> Bytes