This is an early prototype of the SapMachine team, use at your own risk. We don't provide any guarantees regarding functionality or security.
A Java library and CLI for parsing, transforming, and redacting HotSpot hs_err crash report files.
Parse an hs_err file:
import me.bechberger.jhserr.HsErrReport;
import me.bechberger.jhserr.parser.HsErrParser;
HsErrReport report = HsErrParser.parse(Path.of("hs_err_pid12345.log"));
System.out.println(report.header().crashReason());Redact sensitive information:
import me.bechberger.jhserr.transform.RedactionTransformer;
RedactionTransformer redactor = RedactionTransformer.withDefaults();
HsErrReport redacted = redactor.transform(report);
Files.writeString(Path.of("redacted.log"), redacted.toString());- Full-fidelity parsing: Parse any hs_err crash report into a typed model.
Round-trip:
parse(text).toString()reproduces the original file. - Typed model: 20+ section item types including thread info, stack frames, registers, signal info, stack bounds, memory info, OS info, CPU info, dynamic libraries, VM arguments, environment variables, heap info, and more.
- Visitor pattern: Walk the model tree with
HsErrVisitor— override only the visit methods you need. - Transformer pattern:
HsErrTransformerprovides identity-transforming base class. Subclass to selectively modify report contents. - Redaction:
RedactionTransformerstrips usernames, paths, hostnames, PIDs, IP addresses, env vars, and other sensitive data from crash reports. Configurable viaRedactionConfigwith presets (minimal, aggressive) and JSON config files.sensitivePathPrefixessupports glob patterns (*,**,?) alongside literal prefixes. Path matching is boundary-aware —/privmatches/priv/varbut not/private. - JSON serialization: Full Jackson-based JSON serialization and deserialization
via
HsErrJson. Supports round-trip JSON ↔ model. - CLI tool: Two commands —
redactfor stripping sensitive data,jsonfor converting between text and JSON (withto,from,schemasubcommands). - Syntax highlighting grammars: Ready-to-use grammars for TextMate/VS Code, highlight.js, and CodeMirror — all generated from a single YAML spec.
This repository includes a dedicated VS Code syntax highlighter plugin for
hs_err files in vscode-plugin.
Install from VS Code Marketplace: https://marketplace.visualstudio.com/items?itemName=bechberger.hserr-syntax
- Extension folder:
vscode-plugin - TextMate grammar source:
hserr-grammar/textmate/hserr.tmLanguage.json - CodeMirror grammar source:
hserr-grammar/codemirror/hserr.ts
The extension copies the TextMate grammar from hserr-grammar at build/package time.
Build/package locally:
cd vscode-plugin
npm install
npm run compile
npx @vscode/vsce packageInstall the generated VSIX:
code --install-extension hserr-syntax-*.vsix<dependency>
<groupId>me.bechberger</groupId>
<artifactId>jhserr</artifactId>
<version>0.1.0</version>
</dependency>The CLI has three commands: redact, json, and roundtrip.
# Redact sensitive data (output on stdout, summary on stderr)
java -jar jhserr.jar redact hs_err_pid12345.log
# Redact with output to file
java -jar jhserr.jar redact -o redacted.log hs_err_pid12345.log
# Scan for sensitive information only (no output)
java -jar jhserr.jar redact --scan hs_err_pid12345.log
# Minimal preset (usernames + hostnames only)
java -jar jhserr.jar redact --minimal hs_err_pid12345.log
# Aggressive preset (also strips libs, events, thread names)
java -jar jhserr.jar redact --aggressive hs_err_pid12345.log
# Redact with extra hints
java -jar jhserr.jar redact --username jdoe --hostname myhost \
--sensitive-path /home/jdoe/project hs_err_pid12345.log
# Redact with a config file
java -jar jhserr.jar redact --config redaction.json hs_err_pid12345.log
# Redact and output as JSON
java -jar jhserr.jar redact --json hs_err_pid12345.log
# Generate a default redaction config
java -jar jhserr.jar redact --generate-config
java -jar jhserr.jar redact --generate-config -o redaction.json# Convert hs_err to JSON
java -jar jhserr.jar json to hs_err_pid12345.log
# Convert hs_err to JSON file
java -jar jhserr.jar json to -o report.json hs_err_pid12345.log
# Convert JSON back to hs_err text
java -jar jhserr.jar json from report.json
# Convert JSON back to text file
java -jar jhserr.jar json from -o restored.log report.json
# Print the JSON schema
java -jar jhserr.jar json schema
java -jar jhserr.jar json schema -o schema.json# Run text roundtrip checks for all hs_err files in a directory
java -jar jhserr.jar roundtrip sample-hserrs/new
# Run text + JSON roundtrip checks
java -jar jhserr.jar roundtrip --json sample-hserrs/new// Parse
HsErrReport report = HsErrParser.parse(Path.of("hs_err_pid12345.log"));
// Access typed sections
ThreadSection thread = report.thread();
SignalInfo signal = thread.signalInfo(); // parsed signal name, number, address
StackBoundsInfo stack = thread.stackBoundsInfo(); // stack bottom, top, sp, free space
List<StackFrame> frames = thread.nativeFrames().frames();
ProcessSection process = report.process();
int uid = process.uidInfo().uid();
SystemSection system = report.system();
OsInfo os = system.osInfo();
String uname = os.uname(); // full uname string
String loadAvg = os.loadAverage(); // parsed load average
CpuInfo cpu = system.cpuInfo();
int cores = cpu.totalCpus();
// Walk with visitor
report.accept(new HsErrVisitor() {
@Override
public void visitNamedSection(NamedSection section) {
System.out.println(section.name());
}
});
// Transform
HsErrTransformer transformer = new HsErrTransformer() {
@Override
protected SectionItem transformNamedSection(NamedSection section) {
return new NamedSection(section.name().toUpperCase(), section.lines());
}
};
HsErrReport transformed = transformer.transform(report);
// Scan for sensitive information
RedactionEngine engine = new RedactionEngine();
report.accept(engine);
System.out.println("Usernames: " + engine.usernames());
System.out.println("Hostnames: " + engine.hostnames());
// Redact with config
RedactionConfig config = new RedactionConfig()
.addAdditionalUsername("jdoe")
.setRedactThreadNames(true)
.setRemoveDynamicLibraries(true);
RedactionTransformer redactor = new RedactionTransformer(config);
HsErrReport redacted = redactor.transform(report);
System.err.println("Redacted: " + redactor.redactions());
// JSON round-trip
String json = HsErrJson.toJson(report);
HsErrReport fromJson = HsErrJson.fromJson(json);The redaction config can be loaded from JSON. Generate a default config:
java -jar jhserr.jar redact --generate-configCategories (all enabled by default unless noted):
| Category | Default | Description |
|---|---|---|
redactUsernames |
on | Usernames found in paths (/Users/X/, /home/X/) |
redactHostnames |
on | Hostnames from summary and uname |
redactEnvVars |
on | Environment variable values (except safe list) |
redactPaths |
on | Sensitive path prefixes (supports globs: *, **, ?) |
redactIpAddresses |
on | IPv4 addresses |
pathMode |
KEEP_FILENAME |
KEEP_FILENAME / REDACT_ALL / KEEP_ALL |
redactThreadNames |
off | Thread names |
removeDynamicLibraries |
off | Remove entire dynamic libraries section |
removeEventLogs |
off | Remove event log sections |
Presets: RedactionConfig.minimal() (usernames + hostnames only),
RedactionConfig.aggressive() (everything + strip libs/events/thread names).
The parsed report is an HsErrReport containing:
- Header — crash reason, signal, JRE version, PID
- Summary — command line, hostname, elapsed time
- ThreadSection — current thread info, signal info, stack bounds, memory info, native/Java frames, registers
- ProcessSection — thread lists, dynamic libraries, VM arguments, environment variables, UID/umask, VM state, heap address info, compilation info, event logs
- SystemSection — OS info (uname, uptime, load average, rlimit), CPU info (cores, features, brand), VM info, and other system details
Section items are modeled as a sealed interface SectionItem with 20+ implementations
including BlankLine, NamedSection, ThreadInfo, FrameList, Registers,
SignalInfo, StackBoundsInfo, MemoryInfo, OsInfo, CpuInfo, VmInfo, and more.
# Build
mvn clean package
# Run tests
mvn test
# Release (requires GPG key + OSSRH credentials)
python3 release.py patchA browser-based version of the parser built with GraalVM Web Image (compiles Java to WASM). Drag & drop an hs_err file to parse, redact, and view a diff — all client-side.
Features:
- 5 tabs: editable source (with syntax highlighting), highlighted read-only view, JSON, redacted view, line-level diff
- hs_err syntax highlighting: CodeMirror mode in the source editor, highlight.js in the highlighted tab
- Inline change highlighting: the redacted tab marks only the changed substrings within each line
- CodeMirror JSON editor: syntax-highlighted config editing with bracket matching
- Live config updates: changes to the redaction config apply immediately (debounced)
- Example files: three bundled hs_err files to try without uploading
- Download buttons: export JSON or redacted text
- Persistent config: redaction settings saved in localStorage
The submodule lives in hserr-web/ and requires the following to build:
- GraalVM 25+ (install via
sdk install java 25.0.2-graal) - binaryen v119+ for
wasm-opt(install viabrew install binaryenon macOS orapt install binaryenon Linux) - Maven 3.9+
# First, install the parser library into the local Maven repo
mvn install -DskipTests
# Then build the WASM module
cd hserr-web
mvn package
# Outputs: web/hserr.js + web/hserr.js.wasm
# Open web/index.html in a browserOr use the all-in-one script (auto-detects the latest sdkman GraalVM):
./launch.sh # builds everything and starts a dev server on :8080
PORT=3000 ./launch.sh # use a custom portThe web tool is automatically deployed to GitHub Pages on pushes to main.
Ready-to-use syntax highlighting grammars for hs_err_pid*.log files, all derived from
a single YAML grammar spec.
Available formats:
| Format | File | Use with |
|---|---|---|
| TextMate | hserr.tmLanguage.json |
VS Code extensions, shiki, any TextMate-compatible editor |
| highlight.js | hserr.js |
Browser & Node.js via highlight.js |
| CodeMirror 6 | hserr.ts |
CodeMirror 6 StreamLanguage |
Download from the web: All grammar files are available at parttimenerd.github.io/jhserr/grammars.
Quick usage — highlight.js:
<script src="https://parttimenerd.github.io/jhserr/grammars/hserr.js"></script>
<!-- auto-registers as hljs.getLanguage('hserr') if hljs is loaded -->Quick usage — VS Code extension:
During the web build, these grammars are automatically copied to hserr-web/web/grammars/
for deployment to GitHub Pages.
This project is open to feature requests/suggestions, bug reports etc. via GitHub issues. Contribution and feedback are encouraged and always welcome.
MIT, Copyright 2026 SAP SE or an SAP affiliate company, Johannes Bechberger and contributors