Stripping debug info from jlink runtime images

Photo by Nuno Silva

Using jlink, one can easily create a custom Java runtime image that will only contain the modules required to run a given application. jlink also comes with some additonal plugins, some of which will help to additionaly reduce the size of the produced custom runtime image — namely the compress and the strip-debug plugins.

As its name implies, the strip-debug plugin will remove debugging information out of the output runtime image. With JDK13, this plugin was only stripping Java debug attributes from classes of the output image. Starting JDK13, it has been updated to be more granular and is now, in addition to Java debug attributes, also able to remove native debug symbols from the output custom image.

To invoke it, just append your jlink command with one of the strip*debug* flags but do note the behaviour difference in JDK13.

E.g. jlink --module-path mlib --strip-debug --add-modules com.greetings --output myappruntime

Pre-JDK13 behaviour

  • —-strip-debug : strips out Java debug attributes.

JDK13+ behaviour

  • —-strip-debug : combined debug stripping, i.e. removes the Java debug attributes ( —-strip-java-debug-attributes) and the native debug symbols (--strip-native-debug-symbols).

  • —-strip-java-debug-attributes : strips out the Java debug attributes.

  • —-strip-native-debug-symbols : strips out the native debug symbols.

To remove native debug symbols, the strip-debug plugin relies on the native Linux objcopy utility. If it is not installed (ex. on Alpine Linux) or installed in a non-standard location, you will get the following exception:

java.io.IOException: Cannot run program “objcopy”: error=2, No such file or directory

You can solve that by specifying the path of objcopy:

jlink … --strip-native-debug-symbols objcopy=/usr/bin/objcopy …

This is particularly useful when targeting a different platform.

Caveats

  • Some builds (e.g. Oracle OpenJDK builds and Oracle JDK builds) are already stripping the Java debug attributes so —-strip-java-debug-attributes will be of little use with those.

  • objcopy=<path> only works with --strip-native-debug-symbols not with —-strip-debug.

  • —-strip-native-debug-symbols and —-strip-debug are exclusive.

  • Stripping native debug symbols is platform-dependent and is as of now only supported on Linux.

Conclusion

Improved runtime size is especially important when running Java applications in containers as keeping container images small is key. Moreover, it is always a good practice to avoid carrying bits that will never be used. `jlink is a tool that every Java developer should consider leveraging to achieve this.

Originaly posted on Medium.