Skip to content

Commit c854b32

Browse files
committed
Add MAT CLI Heapdump Command Playbook and OQL Recipes documentation
1 parent b4ead45 commit c854b32

4 files changed

Lines changed: 352 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
name: mat-cli-heapdump-investigator
3+
description: Investigate Java heap dumps with Eclipse MAT CLI. Use when Codex needs to analyze `.hprof`, `.phd`, or companion javacore-backed heap dumps to diagnose memory leaks, find the biggest retained objects or dominators, inspect object field values for a class instance, trace paths to GC roots, review thread state or stack snippets available in the dump, or run MAT reports and OQL queries for deeper heap forensics.
4+
---
5+
6+
# MAT CLI Heapdump Investigator
7+
8+
## Overview
9+
10+
Use `mat-cli` as the first-line tool for Java heap-dump triage. Prefer the dedicated CLI commands with stable JSON contracts, then escalate to `query` or `oql` only when a direct command cannot answer the question cleanly.
11+
12+
## Start Here
13+
14+
- Confirm `mat-cli` is reachable with `mat-cli --help`.
15+
- Prefer `--format json` while reasoning, then rerun one or two focused commands with `--format text` when you need readable excerpts for the user.
16+
- Start broad and narrow gradually: `summary` -> `top-consumers` or `histogram` -> `instances` -> `inspect-object` -> `path2gc`.
17+
- Use absolute heap paths and keep every suspect object's `0x...` address in your notes.
18+
- Keep companion files beside the heap when possible. For OpenJ9 `.phd` dumps, a nearby `javacore` can improve thread analysis.
19+
- Use `--query-file` or `--command-file` for long expressions, embedded quotes, regexes, baseline paths, or inner class names containing `$`.
20+
- If `mat-cli` is not installed, install it first with `brew install demogorgon314/mat-cli/mat-cli`. If Homebrew is unavailable but the current workspace is the MAT source tree, build it from the `parent/` module with `mvn clean package -DskipTests -Dmat-product=mat-cli`.
21+
22+
## Core Workflow
23+
24+
1. Establish the snapshot baseline.
25+
26+
```bash
27+
mat-cli summary <heap> --format json
28+
mat-cli threads <heap> --format json --limit 20
29+
```
30+
31+
Use `summary` for heap format, object count, class count, and used heap. Use `threads` early when the leak might be thread-local, blocked, or finalizer-related. Remember that thread output is best-effort from the heap dump, not a full `jstack`.
32+
33+
2. Identify dominant retainers and the biggest objects.
34+
35+
```bash
36+
mat-cli top-consumers <heap> --format json --limit 20 --depth 3
37+
mat-cli histogram <heap> --format json --limit 50
38+
```
39+
40+
Use `top-consumers` to find the biggest retained objects, classes, class loaders, and packages. Use `histogram` to spot explosive class counts and approximate retained sizes. Keep the `objectAddress` values from `biggestObjects`, `classes`, and `classLoaders` for follow-up drills.
41+
42+
3. Narrow to a suspect class or instance set.
43+
44+
```bash
45+
mat-cli instances <heap> --class com.example.CacheEntry --format json --limit 50
46+
mat-cli instances <heap> --class-regex 'com\\.example\\..*Cache.*' --format json --limit 50
47+
mat-cli instances <heap> --class-contains ThreadLocal --include-subclasses --format json --limit 50
48+
```
49+
50+
Use `instances` when the user names a class or when `histogram` points at one. Prefer `--class` for exact matches. Use regex or contains matching only when the package or suffix is uncertain. Add `--include-subclasses` only when inheritance matters.
51+
52+
4. Inspect concrete object state and field values.
53+
54+
```bash
55+
mat-cli inspect-object <heap> --object 0x1234abcd --format json --depth 4 --limit 20
56+
mat-cli inspect-object <heap> --object 0x1234abcd --select-field value --format json --limit 20
57+
mat-cli inspect-object <heap> --object 0x1234abcd --field-path cleaner.offsetMap --format json
58+
```
59+
60+
Use `inspect-object` to answer questions like "what value is stored in this object's fields?" Prefer `--field-path` when you need one nested value quickly. Prefer `--select-field` when one direct field is the real payload. Increase `--depth` carefully; the default is intentionally conservative. Use `--show-nulls` only when missing references are relevant to the diagnosis.
61+
62+
5. Explain why a suspect survives GC.
63+
64+
```bash
65+
mat-cli path2gc <heap> --object 0x1234abcd --format json --depth 8 --limit 20
66+
mat-cli query <heap> --command "show_dominator_tree 0x1234abcd" --format json --limit 20 --depth 4
67+
```
68+
69+
Use `path2gc` for the shortest retaining path to GC roots. Use `show_dominator_tree` when `path2gc` is too narrow and you need local dominator context. If `path2gc` says the object is already a GC root, say that explicitly and pivot back to `inspect-object`, `threads`, or a dominator query.
70+
71+
6. Run advanced MAT queries only after the direct commands.
72+
73+
```bash
74+
mat-cli list-queries --format json
75+
mat-cli describe-query thread_overview --format json
76+
mat-cli query <heap> --command "thread_overview" --format json
77+
mat-cli query <heap> --command "finalizer_thread" --format json
78+
mat-cli query <heap> --command "default_report org.eclipse.mat.api:suspects" --format json
79+
```
80+
81+
Use `query` for registered MAT reports and analyses that do not have dedicated CLI wrappers. Inspect the query id first if you are unsure about syntax or arguments.
82+
83+
## Reporting Rules
84+
85+
- Separate shallow heap from retained heap.
86+
- Quote exact class names and object addresses.
87+
- Treat histogram retained sizes as approximate unless the command guarantees otherwise.
88+
- Tie each leak suspect to at least two pieces of evidence, such as a top-consumers row, a retained path, a field value, a thread, or a MAT report section.
89+
- Call out uncertainty clearly when stack frames are missing or when the dump only offers best-effort thread metadata.
90+
- Prefer a short evidence chain over dumping raw JSON or huge tables back to the user.
91+
92+
## References
93+
94+
- Read [references/command-playbook.md](references/command-playbook.md) for ready-to-run commands and advanced MAT query patterns.
95+
- Read [references/oql-recipes.md](references/oql-recipes.md) when built-in commands are not enough and you need validated OQL snippets.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "MAT CLI Heapdump Investigator"
3+
short_description: "Investigate Java heap dumps with MAT CLI"
4+
default_prompt: "Use $mat-cli-heapdump-investigator to analyze this heap dump with mat-cli, find leak suspects, inspect retained memory, and explain the results."
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# MAT CLI Heapdump Command Playbook
2+
3+
## Contents
4+
5+
- Baseline and schemas
6+
- Biggest objects and dominators
7+
- Class-focused drilldown
8+
- Object inspection and value extraction
9+
- Retention paths and merged paths
10+
- Threads, finalizers, and reports
11+
- Comparing two dumps
12+
- Failure handling
13+
14+
## Baseline and Schemas
15+
16+
If `mat-cli` is missing, install it with:
17+
18+
```bash
19+
brew install demogorgon314/mat-cli/mat-cli
20+
```
21+
22+
If Homebrew is unavailable and you are already inside the MAT source tree, fall back to building the standalone CLI from `parent/`.
23+
24+
Use these first:
25+
26+
```bash
27+
mat-cli summary <heap> --format json
28+
mat-cli describe top-consumers --format json
29+
mat-cli schema threads --format json
30+
```
31+
32+
Use `describe` or `schema` when you need to know the stable JSON payload before scripting against a command. The dedicated commands already return stable `mat-cli/v2` envelopes, so prefer them over free-form MAT queries whenever possible.
33+
34+
## Biggest Objects and Dominators
35+
36+
Start with retained heap, not just object count:
37+
38+
```bash
39+
mat-cli top-consumers <heap> --format json --limit 20 --depth 3
40+
mat-cli histogram <heap> --format json --limit 50
41+
```
42+
43+
Interpret the output like this:
44+
45+
- `top-consumers` answers "what dominates retained memory right now?"
46+
- `histogram` answers "which classes are numerous or large in aggregate?"
47+
- `top-consumers.biggestObjects[].objectAddress` is the best bridge into `inspect-object`, `path2gc`, and `show_dominator_tree`.
48+
- `histogram` is a table result. Look for `class_name`, instance count, shallow heap, and retained heap columns.
49+
50+
Use a smaller `--limit` when you only need the top suspects. Increase `--depth` on `top-consumers` when package aggregation matters.
51+
52+
## Class-Focused Drilldown
53+
54+
Use `instances` once a class looks suspicious:
55+
56+
```bash
57+
mat-cli instances <heap> --class com.example.CacheEntry --format json --limit 20
58+
mat-cli instances <heap> --class-regex 'com\\.example\\..*Cache.*' --format json --limit 20
59+
mat-cli instances <heap> --class-contains ThreadLocal --include-subclasses --format json --limit 50
60+
```
61+
62+
Choose the selector deliberately:
63+
64+
- Use `--class` for exact FQCN matches.
65+
- Use `--class-regex` for uncertain package names or multiple related classes.
66+
- Use `--class-contains` for fast discovery when the class name fragment is all you know.
67+
- Use `--include-subclasses` only when the leak might live in subtype instances.
68+
69+
## Object Inspection and Value Extraction
70+
71+
Use `inspect-object` for single-object truth:
72+
73+
```bash
74+
mat-cli inspect-object <heap> --object 0x1234abcd --format json --depth 4 --limit 20
75+
mat-cli inspect-object <heap> --object 0x1234abcd --select-field value --format json --limit 20
76+
mat-cli inspect-object <heap> --object 0x1234abcd --field-path cleaner.offsetMap --format json
77+
mat-cli inspect-object <heap> --object 0x1234abcd --format text --field-path count
78+
```
79+
80+
Use it this way:
81+
82+
- Reach for `--field-path` when the user asks for one concrete nested value.
83+
- Reach for `--select-field` when the root object is just a wrapper and one direct field is the real payload.
84+
- Watch for `_meta.value.kind` previews in JSON. MAT can surface text previews or byte-array previews without walking the whole subtree.
85+
- Use `--show-nulls` only when null references are part of the bug story.
86+
87+
If a field path fails, fix the path instead of assuming the value is null. MAT reports missing fields explicitly.
88+
89+
## Retention Paths and Merged Paths
90+
91+
Use the simplest retention question first:
92+
93+
```bash
94+
mat-cli path2gc <heap> --object 0x1234abcd --format json --depth 8 --limit 20
95+
mat-cli query <heap> --command "show_dominator_tree 0x1234abcd" --format json --limit 20 --depth 4
96+
mat-cli query <heap> --command "merge_shortest_paths -groupby FROM_GC_ROOTS com.example.CacheEntry" --format json --limit 20 --depth 4
97+
```
98+
99+
Pick the command based on the question:
100+
101+
- `path2gc` finds the shortest retention chain for one object.
102+
- `show_dominator_tree` shows the local dominator neighborhood for one suspect.
103+
- `merge_shortest_paths` is useful when many instances of the same class appear to leak through the same retaining structure.
104+
105+
If `path2gc` reports that the object is already a GC root, stop searching for an upstream holder and inspect the root object's own fields, thread ownership, or role.
106+
107+
## Threads, Finalizers, and Reports
108+
109+
Use dedicated thread support first:
110+
111+
```bash
112+
mat-cli threads <heap> --format json --limit 50
113+
mat-cli query <heap> --command "thread_overview" --format json
114+
mat-cli query <heap> --command "finalizer_thread" --format json
115+
mat-cli query <heap> --command "finalizer_thread_locals" --format json
116+
```
117+
118+
Use MAT reports when you need a broader narrative:
119+
120+
```bash
121+
mat-cli query <heap> --command "default_report org.eclipse.mat.api:overview" --format json
122+
mat-cli query <heap> --command "default_report org.eclipse.mat.api:suspects" --format json
123+
mat-cli query <heap> --command "default_report org.eclipse.mat.api:top_components" --format json
124+
```
125+
126+
Remember:
127+
128+
- `threads` and `thread_overview` are best-effort views of heap data, not a runtime thread dump.
129+
- `default_report` commands often return section-style results. Summarize the important sections instead of replaying the full structure.
130+
- Use `list-queries` and `describe-query` before calling obscure MAT query ids.
131+
132+
## Comparing Two Dumps
133+
134+
When you have a baseline and a current dump from comparable workloads, use MAT's compare reports:
135+
136+
```bash
137+
mat-cli query <new-heap> --command "default_report org.eclipse.mat.api:overview2 -params baseline=/abs/path/baseline.hprof" --format json
138+
mat-cli query <new-heap> --command "default_report org.eclipse.mat.api:suspects2 -params baseline=/abs/path/baseline.hprof" --format json
139+
```
140+
141+
Prefer `--command-file` if the baseline path contains spaces or the command grows longer.
142+
143+
## Failure Handling
144+
145+
Use these recovery moves:
146+
147+
- `Unknown MAT query`: run `mat-cli list-queries --format json` and `mat-cli describe-query <id> --format json`.
148+
- OQL syntax problems: move the expression into a UTF-8 file and use `--query-file`.
149+
- MAT query syntax problems: move the command into a UTF-8 file and use `--command-file`.
150+
- Invalid `path2gc` address: verify the address with `mat-cli oql <heap> --query "SELECT * FROM OBJECTS 0x1234abcd" --format json`.
151+
- Too much data: lower `--limit`, lower `--depth`, or pivot from `query` to a dedicated command.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# MAT CLI Heapdump OQL Recipes
2+
3+
Use these only after the dedicated commands fail to answer the question cleanly. For one object and one field, `inspect-object` is usually simpler and safer than OQL.
4+
5+
## Useful Pseudo Fields
6+
7+
MAT OQL exposes metadata fields that are useful in leak analysis:
8+
9+
- `@objectAddress`
10+
- `@usedHeapSize`
11+
- `@retainedHeapSize`
12+
- `@name`
13+
14+
Use them to connect OQL results back to `inspect-object`, `path2gc`, or `top-consumers`.
15+
16+
## List Objects with Address and Readable Value
17+
18+
Validated in the CLI tests:
19+
20+
```sql
21+
select s.@objectAddress as ADDRESS, toString(s) as VALUE
22+
from java.lang.String s
23+
```
24+
25+
Run it with:
26+
27+
```bash
28+
mat-cli oql <heap> --query-file strings.oql --format json --limit 20
29+
```
30+
31+
Use this pattern when you need both an address and a human-readable rendering.
32+
33+
## Jump to One Object by Address
34+
35+
```sql
36+
SELECT * FROM OBJECTS 0x1234abcd
37+
```
38+
39+
Use this to verify that an address from another command is valid before running `path2gc` or a more specific OQL expression.
40+
41+
## Find Large or Suspicious String Objects
42+
43+
Validated in the OQL tests:
44+
45+
```sql
46+
SELECT * FROM java.lang.String s
47+
WHERE s.count > 100 AND s.@retainedHeapSize > s.@usedHeapSize
48+
```
49+
50+
Use this pattern to find payload-heavy strings whose retention looks disproportionate.
51+
52+
## Filter by Rendered Value
53+
54+
Validated in the OQL tests:
55+
56+
```sql
57+
SELECT * FROM java.lang.String s
58+
WHERE toString(s) LIKE "java.*"
59+
```
60+
61+
This is useful when class identity is not enough and the content matters.
62+
63+
## Ask for Dominators from OQL
64+
65+
Validated in the OQL tests:
66+
67+
```sql
68+
select objects dominators(s)
69+
from objects 0x1234abcd s
70+
```
71+
72+
Use this when you need a quick dominator set in OQL form. For user-facing explanations, `path2gc` or `show_dominator_tree` is often easier to interpret.
73+
74+
## Collapse to Distinct Classes
75+
76+
Validated in the OQL tests:
77+
78+
```sql
79+
select distinct objects classof(s)
80+
from java.lang.String s
81+
```
82+
83+
Use this pattern when a broader instance query returns mixed runtime types and you want the concrete classes involved.
84+
85+
## Inspect Map-Like Structures
86+
87+
Validated in the OQL tests:
88+
89+
```sql
90+
SELECT m AS map,
91+
classof(m).@name AS type,
92+
m[0:-1].size() AS size
93+
FROM INSTANCEOF java.util.AbstractMap m
94+
```
95+
96+
Use this to find oversized maps before drilling into their entries with `inspect-object` or a more specific OQL query.
97+
98+
## Quoting Guidance
99+
100+
- Prefer `--query-file` for multi-line OQL.
101+
- Prefer `--query-file` when the expression contains `$`, regexes, nested quotes, or long baseline-dependent fragments.
102+
- If MAT parses the query but execution fails, narrow the scope instead of making the expression more complex immediately.

0 commit comments

Comments
 (0)