Official Documentation

Ponder End-User Guide

Everything you need to index, inspect, and diagnose Java heap dumps with Ponder.

This guide assumes you have a pre-built ponder binary and a Java .hprof heap dump.


# 1. Files You Need in Your Working Directory

ponder looks for two files in the directory where you run it:

FilePurpose
license.datSigned license file
state.datSupporting anchor for license file

If either is missing, every command (except --help / --version) exits with a license error.

You should receive these from whoever provided the binary. If you are evaluating the project, copies exist in the repository under Licencing/tester/.


# macOS Gatekeeper Note

If you downloaded a prebuilt ponder binary (for example, ponder-aarch64-macos) on macOS, Gatekeeper may refuse to run it and report operation not permitted. This happens because downloaded executables are tagged with the com.apple.quarantine extended attribute, which the kernel enforces even for valid, ad-hoc signed Mach-O binaries.

Remove the quarantine flag:

bash
xattr -d com.apple.quarantine /path/to/ponder

Then run the binary normally:

bash
/path/to/ponder --help

# 2. Getting Help

bash
# Top-level help
ponder --help

# Per-command help
ponder index --help
ponder histogram --help
ponder roots --help

The built-in help shows usage, options, examples, and exit codes for each command.


# 3. Optional: Create a Config File

To avoid typing --index-dir every time, create ~/.config/ponder/config.json:

bash
mkdir -p ~/.config/ponder
cat > ~/.config/ponder/config.json <<'EOF'
{
  "index-dir": "/path/to/your/indexes",
  "memory-budget-mb": 4096
}
EOF

# Config behavior

FieldMeaning
index-dirFor index/overview, this is a base directory.
memory-budget-mbsorting budget and should not be changed

Override the config path with --config /path/to/config.json, or override just the index dir with --index-dir <dir>.


# 4. The Standard Workflow

Ponder is a two-pass tool:

  1. index — scan the .hprof once and write persistent index files.
  2. overview — build a small overview.bin cache for fast summary queries.
  3. Query commands — read from the index/cache.

You must run index, then overview, before any query.

# 4.1 Index the dump

bash
ponder index path/to/heap.hprof --index-dir path/to/heap.idx

On success it prints a JSON summary:

json
{"status":"complete","index_dir":"path/to/heap.idx","n_objects":170877,"n_classes":1844,"n_edges":262839,"n_roots":1851,...}

If an up-to-date index already exists, it prints:

json
{"status":"reused","index_dir":"path/to/heap.idx"}
OptionMeaning
--index-dir <dir>Where to write the index
--memory-budget-mb <n>RAM budget for sorting (default 4096)
--forceRebuild even if a matching index exists
--no-progressSuppress progress spinner

# 4.2 Build the overview cache

bash
ponder overview path/to/heap.hprof --index-dir path/to/heap.idx

This creates overview.bin inside the index directory.

Run it again after re-indexing, or use --force to overwrite.


# 5. Summary Commands (use overview.bin)

# info — high-level dump summary

bash
ponder info --index-dir path/to/heap.idx

Sample output:

text
Header:
  id_size:    8 bytes
  timestamp:  1783429843270

Summary:
  total objects:  169033
  classloaders:   4
  classes:        1844
  arrays:         67091
  heap bytes:     10137438

# histogram — top classes by shallow heap

bash
# CSV output, top 15 by bytes
ponder histogram --index-dir path/to/heap.idx

# Human-readable table
ponder histogram --index-dir path/to/heap.idx --view

# Sort by instance count
ponder histogram --index-dir path/to/heap.idx --view -s

# Limit to 20
ponder histogram --index-dir path/to/heap.idx --view -l 20

Output columns: class, instances, shallow_bytes.

OptionMeaning
-l N, --limit NTop N rows (default 15)
--viewFormatted table instead of CSV
-s, --sort-instancesSort by instance count, not bytes
--match <regex>Include only matching class names
--exclude <regex>Omit matching class names
--min-bytes <n>Minimum total shallow bytes
--min-instances <n>Minimum instance count

Regex notes: supports ^, $, ., *, +, ?, escaped literals, and character classes.

# classes — loaded class metadata

bash
ponder classes --index-dir path/to/heap.idx --view

Output columns: class, superclass, instance_size.

OptionMeaning
--match <regex>Filter class names
--exclude <regex>Exclude class names
--min-instance-size <n>Minimum bytes per instance

# 6. Object Query Commands (use the persistent index)

# objects — list object IDs by class

bash
ponder objects 'com.example.heapforge.User' --index-dir path/to/heap.idx --limit 10

Output is JSON:

json
{
  "pattern": "com.example.heapforge.User",
  "limit": 10,
  "offset": 0,
  "items": [
    {"id": "0x0000000708827488", "ordinal": 4001, "class": "com/example/heapforge/User", "kind": "instance", "shallow_bytes": 85}
  ],
  "next_offset": 1
}
OptionMeaning
--limit NMax objects (default 100)
--offset NSkip first N matches
--reverseDescending ordinal order

# sample — decoded representative objects

bash
ponder sample 'com.example.heapforge.User' --index-dir path/to/heap.idx --limit 3

Returns the same objects as objects, but with field names and values:

json
{
  "items": [{
    "id": "0x0000000708827488",
    "class": "com/example/heapforge/User",
    "shallow_bytes": 85,
    "fields": [
      {"name": "id", "value": 1756},
      {"name": "name", "ref": "0x...", "ordinal": 3998, "class": "java/lang/String"},
      {"name": "active", "value": true}
    ]
  }]
}

# object — decode one object by ID

bash
ponder object 0x0000000708827488 --index-dir path/to/heap.idx

# 7. Reference-Tracing Commands

These commands walk the heap graph built during indexing.

# refs-from — outgoing references

bash
ponder refs-from 0x0000000708827488 --index-dir path/to/heap.idx --limit 10

Sample:

json
{
  "object": "0x0000000708827488",
  "direction": "outbound",
  "items": [
    {"id": "0x...", "ordinal": 3998, "class": "java/lang/String", "relation": "name"}
  ],
  "next_offset": 5
}

# refs-to — incoming references

bash
ponder refs-to 0x0000000708827488 --index-dir path/to/heap.idx --limit 10

Use this to answer "who is holding this object alive?"

# roots — shortest path to a GC root

bash
ponder roots 0x0000000708827488 --index-dir path/to/heap.idx --max-visited 10000

This is the classic leak-analysis command. It performs a breadth-first search back to the nearest GC root and prints the path:

json
{
  "found": true,
  "truncated": false,
  "path": [
    {"id": null, "ordinal": 170877, "class": "virtual root"},
    {"id": "0x...", "class": "com/example/heapforge/UserRepository"},
    {"id": "0x...", "class": "java/util/concurrent/ConcurrentHashMap"},
    {"id": "0x...", "class": "com/example/heapforge/User"}
  ]
}
OptionMeaning
--max-visited <n>Cap BFS node visits

# tree — bounded expansion

bash
# Outbound tree
ponder tree 0x0000000708827488 --index-dir path/to/heap.idx --direction from --depth 3 --max-nodes 50

# Inbound tree
ponder tree 0x0000000708827488 --index-dir path/to/heap.idx --direction to --depth 3 --max-nodes 50
OptionMeaning
`--direction from\to`Follow outbound or inbound refs (default from)
--depth <n>Max depth
--max-nodes <n>Max nodes in output

# 8. Complete Example Session

bash
# 1. Place heap dump file
#copy heap dump to the location where binary and license and state files exist

# 2. Index
ponder index production-heap.hprof --index-dir production-heap.idx

# 3. Overview
ponder overview production-heap.hprof --index-dir production-heap.idx

# 4. Summarize
ponder info --index-dir production-heap.idx
ponder histogram --index-dir production-heap.idx --view -l 20

# 5. Find suspicious class
ponder histogram --index-dir production-heap.idx --match '^com\.mycompany\.' --view -l 10

# 6. Sample instances
ponder sample 'com.mycompany.SessionContext' --index-dir production-heap.idx --limit 3

# 7. Pick an object and trace it
ID=$(ponder objects 'com.mycompany.SessionContext' --index-dir production-heap.idx --limit 1 | python3 -c "import sys,json; print(json.load(sys.stdin)['items'][0]['id'])")
ponder roots "$ID" --index-dir production-heap.idx --max-visited 50000
ponder tree "$ID" --index-dir production-heap.idx --direction to --depth 4 --max-nodes 100

# 9. Output Formats

CommandDefaultWith --view
index, overviewJSON
infoHuman table
histogram, classesCSVHuman table
objects, sample, objectJSON
refs-from, refs-to, roots, treeJSON

# 10. Environment Variables

VariableEffect
NO_COLOR=1Disable colored output
FORCE_COLOR=1Force colored output even when not a TTY
XDGCONFIGHOMEChanges default config search path

# 11. Common Errors

ErrorCauseFix
license file not foundlicense.dat missing in cwdCopy license file into cwd
state file is corruptstate.dat missing / tamperedCopy valid state.dat into cwd
overview cache not found; run 'ponder overview ...'Querying before overviewRun overview after index
index not found; run 'ponder index ...'Missing or wrong --index-dirCheck path, run index first
object id not found in indexID does not exist or wrong formatUse IDs returned by objects

# 12. Quick Command Reference

CommandWhat it doesNeeds
index <dump>Build persistent indexlicense.dat, state.dat
overview <dump>Build overview.bin cacheExisting index
infoDump summaryOverview cache
histogramClass usage by size/countOverview cache
classesClass metadataOverview cache
objects <regex>Object IDs by classIndex
sample <regex>Decoded object samplesIndex
object <id>Single object decodeIndex
refs-from <id>Outbound refsIndex
refs-to <id>Inbound refsIndex
roots <id>Shortest path to GC rootIndex
tree <id>Bounded ref treeIndex

Ready to try Ponder?

Join the waitlist