Skip to main content
Article

Heap Analysis Without Leaving the Browser: Eclipse MAT on GitHub Codespaces

9 min read 2 views

Some of the most useful files an integration consultant ever receives are also the most awkward to open. A production heap dump from a misbehaving WSO2 node typically arrives as a multi-gigabyte .hprof file, often through a chain of SSH hops and SFTP transfers. The expectation is then that you will load it into Eclipse Memory Analyzer on your laptop and have an answer by morning. The problem is that a working laptop has 16 GB of RAM, a chunk of which is already gone to the usual workload, and a 5 GB heap dump needs at least that much heap given to MAT itself to analyse comfortably.

The pragmatic solution we have settled on is to do the analysis inside a GitHub Codespace. The browser-based VS Code editor, a 32 GB Linux container, and a headless MAT install will get you from "I have a heap dump" to "I have a Leak Suspects report" in under an hour, without installing anything on the laptop or fighting corporate antivirus over a 5 GB binary.

Why not just run MAT locally

The default workflow with MAT is fine for small heap dumps. You download the desktop build, edit MemoryAnalyzer.ini to raise its heap above the dump size, and load the file. For a 1 GB hprof this is unremarkable.

It stops being unremarkable around the 3 to 4 GB mark. MAT needs roughly the size of the dump in heap to parse it, plus some headroom for working memory. On a laptop running a mail client, a chat client, a browser with thirty tabs, and an IDE, there is rarely 8 to 12 GB of contiguous heap available to give to a single Java process. The parse runs for a while, then either swaps to disk and crawls or fails outright with an OutOfMemoryError of its own.

There is also the data-handling question. Heap dumps contain message payloads, in-flight credentials, session tokens, and anything else that happened to be in JVM memory at the moment of capture. Moving a multi-gigabyte hprof onto a personal laptop, where it then sits in a Downloads folder and possibly a sync client, is not the path of least regret. A Codespace is a short-lived, project-scoped environment that disappears when you stop it.

The shape of the workflow

The end-to-end flow is four steps:

  1. Open a Codespace on the repository that owns the integration.
  2. Resize the Codespace to a machine with enough RAM (16 or 32 GB).
  3. Get the hprof into the Codespace.
  4. Install MAT, run the headless Leak Suspects report, view the result.

The whole thing takes about an hour the first time, and twenty minutes once it is familiar. Below is what each step looks like in practice.

Step 1: Open and resize the Codespace

Any Codespace on the relevant repository will do. The default machine type is usually 4-core, 8 GB. That is not enough for a serious heap dump. MAT needs to allocate a JVM heap larger than the dump file, and the operating system needs the rest.

To resize, open the Command Palette with Ctrl+Shift+P and run Codespaces: Change Machine Type. Pick the largest option your organisation allows. For a 4 to 5 GB dump, 16 GB of RAM is the minimum that works comfortably. For anything above that, ask for 32 GB.

If the command is not available in the editor, the same option exists in the GitHub web UI under Codespaces → ... → Change machine type. The Codespace will stop, resize, and restart. The /workspaces directory contents persist across the resize, so it is safe to do this even after you have started downloading files.

Verify the new size with:

$ free -h
              total        used        free
Mem:           31Gi       3.2Gi       6.9Gi

Step 2: Get the hprof into the Codespace

For files under 1 GB, the simplest approach is drag-and-drop. Open the Explorer panel in VS Code, navigate into a fresh dumps/ folder, and drag the file from Windows Explorer or Finder onto the folder. A progress indicator appears at the bottom of the editor. Keep the browser tab focused. Background tabs are often throttled by the browser, which slows the upload.

For larger files, compress first. A typical heap dump compresses to roughly 15 to 20 per cent of its original size because so much of it is repeated class metadata and zero-padded regions. A multi-gigabyte hprof we worked with recently shrank to well under a gigabyte as a zip. That is the difference between a tense upload and a routine one.

# In PowerShell on Windows, using 7-Zip
& "C:\Program Files\7-Zip\7z.exe" a -tgzip heap-dump.gz heap-dump.hprof

# Or, in WSL or macOS
gzip -k heap-dump.hprof

Once the compressed file is in the Codespace, unpack and clean up:

$ cd /workspaces/<repo>/dumps
$ unzip heap-dump.zip      # or gunzip heap-dump.hprof.gz
$ rm heap-dump.zip
$ ls -lh heap-dump.hprof

Before going further, add the dumps directory to .gitignore. A 4 GB file in the working tree will eventually tempt someone into committing it, and heap dumps must never end up in a repository.

echo "dumps/" >> .gitignore
echo "*.hprof" >> .gitignore

If your laptop cannot reach the Codespace directly (some corporate networks block the GitHub CLI), drag-and-drop in the browser is the reliable fallback. It is slower than gh codespace cp, but it works through any HTTP proxy that lets you reach github.dev in the first place.

Step 3: Install MAT and Java 17

The GitHub universal Codespace image ships with Java 11, but recent MAT releases require Java 17. Install both pieces:

$ sudo apt-get update
$ sudo apt-get install -y openjdk-17-jdk-headless

$ cd /workspaces
$ MAT_VERSION=1.15.0
$ wget -q "https://download.eclipse.org/mat/${MAT_VERSION}/rcp/MemoryAnalyzer-${MAT_VERSION}.20231206-linux.gtk.x86_64.zip" -O mat.zip
$ unzip -q mat.zip && rm mat.zip
$ chmod +x mat/ParseHeapDump.sh

MAT's launcher picks the system Java by default, which is still 11. Tell it to use Java 17 explicitly by prepending two lines to MemoryAnalyzer.ini:

$ JAVA17=/usr/lib/jvm/java-17-openjdk-amd64/bin/java
$ sed -i "1i -vm\n${JAVA17}" /workspaces/mat/MemoryAnalyzer.ini

The order matters: -vm and the path must each be on their own line, and they must appear before the -vmargs block. Verify with head -10 /workspaces/mat/MemoryAnalyzer.ini.

Finally, raise MAT's own heap above the size of the dump. On a 32 GB Codespace, 12 GB is comfortable:

$ sed -i 's/-Xmx[0-9]*[mg]/-Xmx12g/' /workspaces/mat/MemoryAnalyzer.ini

If you skipped the resize and are stuck on an 8 GB machine, try -Xmx6g. It works for dumps up to roughly 4 GB, but the safety margin is thin.

Step 4: Run Leak Suspects

The headless invocation is one line. From the dumps directory:

$ /workspaces/mat/ParseHeapDump.sh heap-dump.hprof org.eclipse.mat.api:suspects

The first run is slow because MAT has to parse the dump and build its index files. Expect ten to twenty minutes for a 4 GB dump on a 4-core machine. CPU will be pinned to a single core for most of that time. The parser is largely single-threaded. Subsequent reports against the same dump reuse the indexes and complete in a minute or two.

When the run finishes you will see a set of .index, .idx, and .a2s files alongside the hprof, plus a heap-dump_Leak_Suspects.zip. Unzip it and serve it as a small HTTP site so the browser tab can open it:

$ unzip -o heap-dump_Leak_Suspects.zip -d leak_suspects
$ cd leak_suspects
$ python3 -m http.server 8080

VS Code detects port 8080 and offers to forward it; the Ports tab is the fallback if the toast does not appear. Either way the URL follows a predictable pattern based on the Codespace name:

https://<codespace-name>-8080.app.github.dev

Opening that URL in a new tab loads the Leak Suspects report, with a pie chart of top dominators, a Problem Suspect summary for each one, and links into the dominator tree.

If you would rather not bother with HTTP at all, right-clicking the report's index.html in the Explorer panel and choosing Download pulls it to the laptop as a small zip (typically under 20 MB) that you can open with any browser locally.

A couple of pitfalls worth knowing

The MAT 1.15 release has a known incompatibility with Java 17 inside one of its supplementary reports, the Top Components analysis. Running it triggers a ClassCastException inside ComponentReportQuery and the report aborts with no output. The Leak Suspects report is unaffected, so this is not a blocker for most investigations, but if you specifically need the top-components breakdown, you will need to fall back to the desktop MAT GUI or use OQL queries instead.

If the Forward a Port dialog reports Unable to forward localhost:8080, the most common cause is that the Python HTTP server is listening on 127.0.0.1 only rather than all interfaces. python3 -m http.server listens on all interfaces by default, so this should be fine, but if you change to a different server, check the bind address.

Be deliberate about treating the Codespace as production-data territory. The hprof inside it contains payloads, tokens, and session state from a live system. Do not switch a forwarded port from Private to Public. Do not commit the dump or the report. Delete the Codespace when the investigation is done. Stopping it is not enough; the disk persists until the Codespace is deleted.

What this gets you

The reason this workflow is worth the setup is that it removes the bottleneck. The most expensive part of a heap-dump investigation is rarely the analysis itself; it is the friction of getting a multi-gigabyte file from a production node onto a machine where MAT can open it, while staying inside whatever data-handling rules the client has. A Codespace with enough RAM, sitting on a network closer to wherever the dump came from, with no persistent local storage to worry about, sidesteps most of that friction.

If your team supports WSO2 or other JVM-based middleware and you find yourself triaging heap dumps more than once a quarter, it is worth building this into your runbook. Drop a .devcontainer/devcontainer.json into the integration repository that installs MAT and Java 17 on container creation, so the next time the call comes in the only setup step is Change Machine Type.

For what to do once the Leak Suspects report opens, the companion white paper Diagnosing JVM Memory Leaks in WSO2 Enterprise Integrator walks the full path from that first pie chart to a named mediator in a named file. The engagement it came out of is written up in The Aggregate That Did Nothing.

If you are running into a heap problem you would like a second pair of eyes on, get in touch with Pinuno. WSO2 and JVM middleware support is part of what our consultancy practice does.

C

Chrystal Akyempon

Related Articles