콘텐츠로 이동
Image 문서0.3

Java 25 FFM 백엔드

최신 안정판 Image 0.3.0 릴리스 기준

라이브러리 모듈

vips-ffm과 Java Foreign Function & Memory API로 공통 libvips API를 구현합니다. Java 25 전용 백엔드이며 호스트 libvips가 지원하면 HEIF 계열 인코딩도 사용할 수 있습니다.

Java 25 서비스에서 libvips와 네이티브 접근을 설정할 수 있을 때 선택하세요. 특히 로컬 대용량 파일은 Path 팩토리가 전체 압축 파일을 JVM 바이트 배열로 만들지 않고 libvips에 직접 경로를 넘깁니다.

Maven 좌표: io.github.bluetape4k.image:bluetape4k-images-vips-java25

중앙 BOM, vips-api, 이 백엔드를 함께 사용합니다.

FfmVipsRuntime은 프로세스 전체에서 하나이며 종료는 되돌릴 수 없습니다. 루트 FfmVipsImageArena.ofShared를 소유하지만 리사이즈·썸네일·크롭 결과는 같은 arena를 공유하고 소유하지 않습니다. 따라서 자식 이미지는 부모 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()
}
}

JVM은 --enable-native-access=ALL-UNNAMED 옵션으로 시작합니다.

  • ffmVipsImageOf, suspendFfmVipsImageOf로 입력을 읽습니다.
  • 로컬 파일은 Path 오버로드를 우선하고 다른 스트림은 제한 안에서 버퍼링합니다.
  • 리사이즈, 썸네일, 크롭과 JPEG/PNG/WebP/AVIF/HEIC 인코딩을 수행합니다.
  • 모든 파생 이미지를 루트 이미지 수명 안에서 사용합니다.

독립된 파이프라인마다 루트 이미지를 하나 만들고 모든 파생 작업이 끝난 뒤 닫으세요. 루트의 use 블록 안에서 만든 자식 이미지를 바깥으로 반환하면 안 됩니다. 파일 경로는 저장소 경계에서 검증하고 네이티브 작업 동시성을 제한합니다.

bluetape4k-images-vips-apivips-ffm으로 구현합니다. Java 25와 시스템 libvips가 필요하고 AVIF/HEIC는 libheif 및 해당 encoder를 포함한 빌드가 필요합니다.

Java 25와 --enable-native-access=ALL-UNNAMED를 사용합니다. Homebrew macOS에서 필요하면 DYLD_LIBRARY_PATH=/opt/homebrew/lib를 설정하세요. 입력 50MiB, 픽셀 150,000,000 기본 제한을 적용하며 Path는 네이티브 로딩 전에 파일 크기를 확인합니다.

디코딩, 연산, 인코딩, 초기화 실패는 공통 예외 계층으로 구분합니다. 네이티브 접근 권한이 없으면 초기화할 때 경고하고 실제 FFM 호출이 실패할 수 있습니다. Arena 정리 실패는 억제된 예외로 보존합니다. 일반 초기화 실패는 재시도할 수 있지만 종료 뒤에는 불가능합니다.

Java 힙뿐 아니라 네이티브 메모리를 함께 관찰하세요. 0.3.0 벤치마크에서 기하 연산의 Java 할당량은 작았지만 libvips 네이티브 메모리는 측정하지 않았습니다. Java 21과 Java 25 측정은 CPU와 네이티브 런타임 간섭을 피하도록 순차 실행합니다.

Java 25에서 ./gradlew :bluetape4k-images-vips-java25:test를 실행합니다. Gradle은 native access, 네이티브 테스트 격리, Homebrew 라이브러리 경로를 설정합니다. runtime 동시성, arena 기반 연산, writer, 속성과 골든 이미지를 검증합니다.

먼저 네이티브 시작과 부모·자식 수명을 테스트하고, 운영 이미지에서 필요한 코덱을 하나씩 스모크 테스트하세요. 마지막으로 실제 입력을 사용해 -Pvips.impl=java25 집중 벤치마크를 실행합니다.

파생 이미지는 루트 arena를 공유하므로 루트보다 오래 살 수 없습니다. Path가 아닌 입력은 50MiB 제한 안에서 버퍼링합니다. AVIF/HEIC enum이 있다는 사실만으로 호스트 코덱 지원을 보장하지 않으며 Java 21 JVM에서는 실행할 수 없습니다.

아래 그림은 0.3.0 배포본의 README 자산을 해당 배포 커밋에서 직접 불러옵니다. 이후 SNAPSHOT이 아니라 이 매뉴얼 버전의 구조와 실행 흐름을 보여 줍니다. 미리보기를 누르면 같은 배포 커밋의 SVG 원본이 열립니다.

Performance vs scrimage 다이어그램

배포본 README: images-vips-java25/README.ko.md

images vips java25 클래스 구조도

배포본 README: images-vips-java25/README.ko.md