Java 25 FFM backend
Latest stable Based on Image release 0.3.0
Library module
Problem
Section titled “Problem”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.
When to use it
Section titled “When to use 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.
Coordinates
Section titled “Coordinates”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.
Core concepts
Section titled “Core concepts”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.
Quick start
Section titled “Quick start”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.
API by task
Section titled “API by task”- Load through
ffmVipsImageOf/suspendFfmVipsImageOf. - Prefer the
Pathoverload 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.
Recommended patterns
Section titled “Recommended patterns”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.
Integrations
Section titled “Integrations”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.
Configuration
Section titled “Configuration”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.
Failure modes
Section titled “Failure modes”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.
Operations
Section titled “Operations”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.
Testing
Section titled “Testing”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.
Workshops and learning path
Section titled “Workshops and learning path”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.
Limitations
Section titled “Limitations”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.
Release diagrams
Section titled “Release diagrams”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
Section titled “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”Release README: images-vips-java25/README.md

