Download Latest Version 4.2.0 release source code.zip (389.2 MB) Google Add to Preferred Sources
Home / 4.2.0
Name Modified Size InfoDownloads / Week
Parent folder
4.2.0 release source code.tar.gz 2026-08-20 389.1 MB
4.2.0 release source code.zip 2026-08-20 389.2 MB
README.md 2026-08-20 3.8 kB
Totals: 3 Items   778.4 MB 1

One fix, and it is the whole point of the release: jave now works when compiled ahead of time by GraalVM native-image.

The bundled ffmpeg is unchanged at 9.0.1, the published packages are unchanged, and there are no API or behaviour changes. Upgrading from 4.1.0 is a version number and nothing else.

GraalVM native image (#276)

Supported, with nothing to configure.

The bundled ffmpeg is a resource inside the jave-nativebin-* jars, extracted at run time by DefaultFFMPEGLocator. native-image discards resources unless something registers them, so an image built against jave contained no binary at all, and the first encoding failed with

Could not find ffmpeg platform executable in resources for <ws/schild/jave/nativebin/ffmpeg-amd64>

which is why it worked when run normally and not after packaging. Nothing to do with Spring Boot, despite where it was usually noticed.

Each jave-nativebin-* jar now ships

META-INF/native-image/ws.schild/<artifactId>/resource-config.json

which native-image discovers on its own. There is nothing to add to your project, no build flags, and no effect on ordinary JVM use. The metadata is generated from the actual contents of each module rather than written by hand, so the registration cannot drift away from the file it is meant to match.

Verified, not assumed

A new workflow installs GraalVM, builds a native image of a smoke test and runs it, with --no-fallback so it cannot quietly produce a JVM image instead:

GraalVM Runtime Environment Oracle GraalVM 21.0.12+7.1
Finished generating 'jave-graalvm-smoke' in 1m 16s.
==> locating the bundled ffmpeg
    extracted /tmp/jave/ffmpeg-amd64 (61892072 bytes)
==> asking it what it can encode
    79 audio encoders
==> encoding something
    wrote smoke-target.mp3 (4640 bytes)
==> reading it back
    format mp3, mp3 (mp3float)

It covers extracting the binary and running the process, not just linking, and it runs on every change that could affect it.

Building an image

Three things are worth knowing.

Depend on one platform package, not jave-all-deps. An image is built for a single platform, so pulling in every binary embeds every binary, several hundred megabytes of ffmpeg the image can never use.

:::xml
<dependency>
    <groupId>ws.schild</groupId>
    <artifactId>jave-core</artifactId>
    <version>4.2.0</version>
</dependency>
<dependency>
    <groupId>ws.schild</groupId>
    <artifactId>jave-nativebin-linux64</artifactId>
    <version>4.2.0</version>
</dependency>

The temporary directory has to be writable, and it has to allow execution. The binary is extracted and then run, so a read only /tmp, or one mounted noexec, fails at that point. That is equally true on the JVM, but it catches people more often in a minimal native image container.

A custom ProcessLocator sidesteps all of it. Point the encoder at an ffmpeg you install into the image yourself and nothing is extracted.

Documented in Usage.

Also

.gitignore now ignores target directories at any depth. The rule matched only one level down, so build output from anything nested deeper was offered up for committing.

Upgrading

Nothing to do beyond the version. If you are coming from 4.0.0 rather than 4.1.0, note the two behaviour changes in 4.1.0: abortEncoding() now actually aborts instead of waiting for ffmpeg to finish, and slf4j-api moved to 2.0.18, which stops an slf4j 1.7 binding from being found.

Full changelog: https://github.com/a-schild/jave2/compare/4.1.0...4.2.0

Source: README.md, updated 2026-08-20