duckdb-hprof

June 28, 2026 ยท View on GitHub

DuckDB extension for querying Java HPROF heap dumps as SQL.

LOAD 'hprof.duckdb_extension';

SELECT * FROM hprof_scan('dump.hprof', 'header');
SELECT * FROM hprof_scan('dump.hprof', 'strings');
SELECT * FROM hprof_scan('dump.hprof', 'instances');

Tables

NameDescription
headerformat, id_size, timestamp_ms
stringsstring_id, value
classesclass_serial, class_object_id, name_string_id
class_dumpsclass layouts: super, loader, instance_size, field counts
instancesobject_id, class_object_id, shallow_size, retained_size
gc_rootsroot_type, object_id, thread_serial, frame_number
heap_summarylive/alloc bytes and counts
object_arraysarray_id, index, element_id (exploded)
primitive_arraysarray_id, element_type, count, bytes
stack_framesframe_id, method, source file, line
stack_tracestrace_serial, thread_serial, frame_count
dominatorsobject_id, dominator_id, distance_to_root

Examples

-- Top classes by retained heap
SELECT s.value, count(*), sum(i.shallow_size), sum(i.retained_size)
FROM hprof_scan('dump.hprof', 'instances') i
JOIN hprof_scan('dump.hprof', 'classes') c ON i.class_object_id = c.class_object_id
JOIN hprof_scan('dump.hprof', 'strings') s ON c.name_string_id = s.string_id
GROUP BY s.value ORDER BY sum(i.retained_size) DESC LIMIT 10;

-- Materialize for fast queries
CREATE TABLE inst AS SELECT * FROM hprof_scan('dump.hprof', 'instances');
CREATE TABLE strs AS SELECT * FROM hprof_scan('dump.hprof', 'strings');

-- Path to GC root
WITH RECURSIVE path AS (
    SELECT object_id, dominator_id, 1 as step
    FROM hprof_scan('dump.hprof', 'dominators')
    WHERE object_id = 21470769184
    UNION ALL
    SELECT d.object_id, d.dominator_id, p.step + 1
    FROM hprof_scan('dump.hprof', 'dominators') d
    JOIN path p ON d.object_id = p.dominator_id
)
SELECT * FROM path ORDER BY step;

Build

make debug      # or make release

Load with DuckDB:

LOAD 'build/debug/hprof.duckdb_extension';