Skip to content
Image docs0.3

Java 25 FFM backend

Latest stable Based on Image release 0.3.0

Library module

This module implements the common libvips API with the Java Foreign Function & Memory API through vips-ffm. It is the Java 25 backend and provides native-file loading plus HEIF-family encoding when the host libvips build supports it.

Choose it for Java 25 services that can install libvips and configure native access. It is especially suitable for large local files because the Path factory calls libvips directly instead of materializing the complete compressed file in a JVM byte array.

Maven coordinate: io.github.bluetape4k.image:bluetape4k-images-vips-java25

Import bluetape4k-dependencies, compile against bluetape4k-images-vips-api, and select this backend at runtime.

FfmVipsRuntime is process-wide and terminal. A root FfmVipsImage owns an Arena.ofShared; transform results share that arena and do not own it. Therefore a child image must never outlive its root/parent arena.

FfmVipsRuntime.init(concurrency = 4)
ffmVipsImageOf(Path.of("input.jpg")).use { source ->
val thumbnail = source.thumbnail(800)
try {
thumbnail.writeTo(Path.of("output.avif"), VipsImageFormat.AVIF)
} finally {
thumbnail.close()
}
}

Start the JVM with --enable-native-access=ALL-UNNAMED.

  • Load through ffmVipsImageOf/suspendFfmVipsImageOf.
  • Prefer the Path overload for local files; non-path streams are bounded and buffered.
  • Resize, thumbnail, crop, and encode JPEG/PNG/WebP/AVIF/HEIC when native codecs exist.
  • Scope every derived image inside the root image’s lifetime.

Create a root image per independent pipeline and close it after all derived work completes. Do not return a derived VipsImage from inside the root’s use block. Validate file paths at the storage boundary and run native work with bounded concurrency.

The module implements bluetape4k-images-vips-api using vips-ffm. It requires Java 25 and system libvips. AVIF/HEIC additionally require a libvips build with libheif and relevant encoders.

Start with Java 25 and --enable-native-access=ALL-UNNAMED. On Homebrew macOS, make /opt/homebrew/lib visible through DYLD_LIBRARY_PATH when necessary. The same 50 MiB input and 150-million pixel defaults apply; Path checks file size before native loading.

Decode, operation, encode, and initialization failures use the common exception hierarchy. Missing native access is warned about at init and may fail in FFM calls. Arena cleanup failures are attached as suppressed exceptions. Initialization can retry after ordinary failure, but never after shutdown.

Monitor native memory as well as managed heap. The release benchmark showed very low Java-side allocation for geometry operations, but explicitly did not measure native libvips memory. Run Java 21 and Java 25 benchmark lanes sequentially to avoid native-runtime and CPU contention.

Run ./gradlew :bluetape4k-images-vips-java25:test on Java 25. Gradle adds the native-access flag, isolates native test classes, and adds Homebrew’s library path when present. Tests cover runtime concurrency, arena-backed operations, writers, properties, and golden images.

First prove native startup and parent/child lifetime in unit tests, then smoke-test each required codec on the production image, and finally run focused -Pvips.impl=java25 benchmarks with representative assets.

Derived images share their root arena and cannot outlive it. Non-path input is buffered under the 50 MiB guard. AVIF/HEIC API availability does not prove host codec support. The backend cannot run on a Java 21 JVM.

These diagrams are loaded directly from README assets published with the 0.3.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.

Performance vs scrimage diagram

Release README: images-vips-java25/README.md

images vips java25 Class Structure diagram

Section titled “images vips java25 Class Structure diagram”

images vips java25 Class Structure diagram

Release README: images-vips-java25/README.md