Redacting Data from Heap Dumps via hprof-redact

Two weeks ago, I showed you how Redacting Sensitive Data from Java Flight Recorder Files is possible using my new jfr-redact tool. This tool also supports redacting information from hs-error files, but it doesn’t handle heap dumps. Sadly, there is currently no support in OpenJDK for redacting these files directly, to quote Volker Simonis’ comment under my last blog post:

There’s also “JDK-8337517: Redacted Heap Dumps” (https://bugs.openjdk.org/browse/JDK-8337517) which unfortunately didn’t receive enough support from upstream 🙁

Well, there is now the tool hprof-redact that allows you to easily null all primitives and strings in the heap dump and even implement your own basic redactions when using it as a library. It’s a small tool (written with femtocli, of course) under MIT license, which we’ll cover in this blog post. Please be aware that it is still an early prototype, but it might already be useful:

./hprof-redact source.hprof output.prof

But first, what are heap dumps?

Continue reading

Femtocli: A small but mighty CLI library for small CLI tools in < 45KB

TL;DR: I built femtocli, a small command-line parsing library with sub-commands, an annotation-based API, and support for parsing Java agent arguments.

Every command-line tool that I, and probably you, write needs a command-line interface (CLI). Writing simply, with one or two options manually, is possible, but becomes tedious fast. Especially when our tool grows, and we add more options and subcommands.

Usually, you would add a library like the fantastic picocli to your project and be fine. It’s a really easy-to-use CLI library with all the features that you would want. So you can write a simple CLI quite quickly and declaratively:

@Command(name = "demo", description = "A demo application")
public class Main implements Runnable {

    @CommandLine.Parameters(index = "0", description = "Some parameter")
    String parameter;

    @Option(names = "--some-flag")
    boolean someFlag;

    @Override
    public void run() { /* print */ }

    public static void main(String[] args) {
        new CommandLine(new Main()).execute(args);
    }
}

The only problem? While the application JAR itself is only around 3KB for these tiny examples, the application JAR with the Picocli 4.7.7 dependency is 407KB.

Is this a problem? It might not be for you, but it certainly can be for small tools like jstall, where the Picocli dependency accounted for over half the JAR size in the minimal version, which is kind of a lot just for the option parsing. Of course, in many situations you don’t care, as there are other libraries, e.g., for JSON parsing, that can easily add multiple megabytes. But for tiny CLI helper tools, it can matter.

I couldn’t find any maintained CLI library with a picocli-like declarative approach and sub-commands under 50KB, so I built one. And the best part: I was able to add all the features I liked (converters, custom footers, …) and ignore the ones I don’t usually need (GraalVM support, ANSI colors, …).

The new library is called femtocli, it requires Java 17 and is MIT licensed:

package me.bechberger.femtocli.examples;

import me.bechberger.femtocli.FemtoCli;
import me.bechberger.femtocli.annotations.Command;
import me.bechberger.femtocli.annotations.Option;

import java.util.concurrent.Callable;

@Command(name = "greet", description = "Greet a person")
class GreetCommand implements Callable<Integer> {
    @Option(names = {"-n", "--name"}, description = "Name to greet", required = true)
    String name;

    @Option(names = {"-c", "--count"}, description = "Count (default: ${DEFAULT-VALUE})", defaultValue = "1")
    int count;

    @Override
    public Integer call() {
        for (int i = 0; i < count; i++) System.out.println("Hello, " + name + "!");
        return 0;
    }
}

@Command(name = "myapp", description = "My CLI application", version = "1.0.0",
        subcommands = {GreetCommand.class})
public class QuickStart implements Runnable {
    public void run() {
        System.out.println("Use 'myapp greet --help'");
    }

    public static void main(String[] args) {
        FemtoCli.run(new QuickStart(), args);
    }
}

Try it:

> ./examples/run.sh QuickStart greet --name=World --count=1
Hello, World!
Continue reading

Redacting Sensitive Data from Java Flight Recorder Files

I few weeks ago, I showed you how to read and write JFR files programmatically. This week we’re using the covered basic-jfr-professor to create a fully fledged (yet still experimental) JFR and hserr file redaction tool called jfr-redact.

Duke the Java mascot redacting information on a sheet of paper using a black marker

TL;DR: Download jfr-redact from GitHub and redact sensitive information like user names, tokens, and keys from files via:

# Using the JAR directly
java -jar jfr-redact.jar redact recording.jfr

# Redact text files
java -jar jfr-redact.jar redact-text hs_err.log
Continue reading

Implement a new JStall Feature with Me

Or: How I use GitHub Copilot to go from feature to idea

A few weeks back, I introduced you to jstall (Quickly Inspect your Java Application with JStall), a tool that analyses what your JVM is currently doing. This week is the first time I’m bringing you in on the development and letting you peek behind the curtains to see how I go from idea to implemented feature. The feature I’ll implement the jvm-support analysis that checks that the JVM running your application is not outdated.

This is the first time I recorded my development process, so I hope you still liked it.

See you on another day for something command-line parser- or redaction-related.

This blog post is part of my work in the SapMachine team at SAP, making profiling easier for everyone.

The Java Version Quiz

Over the last 30 years, Java has added many features, including generics, lambdas, pattern matching, and records. You surely know that lambdas have been introduced in Java eight and records in Java 16, but can you distinguish the other Java versions?

I felt I couldn’t, so I created a tiny little Java game: The Java Version Quiz. In this quiz, you get a Java snippet and have to decide between five different Java versions. Pick the smallest Java version where the snippet is valid code (without using preview features).

The screenshot shows the alpha version of the game, which includes features introduced in Java 1.0alpha2 and 1.0alpha3, including bug fixes. A game version for only the nerdiest of Java connaisseurs. Source is a dump of the alpha2 and alpha3 packages on GitHub.

The game focuses on Java language differences and major runtime differences, which are easy to check without semantic analysis. It’s a by-product of another fun little project.

I hope you learn some new features of Java and discover that it is evolving over the years, while still keeping the syntax similar enough that it’s hard to spot the differences between versions. And if you’re unsure what a specific feature in the shown code snippet is, the quiz gives you a handy description.

If you find any issues or have new code examples, feel free to contribute to the quiz on GitHub.

See you in another week for another blog post on something JFR-related.