Нативная сборка
Обычное Java-приложение запускается на JVM: виртуальная машина загружает классы, прогревается и только потом работает быстро. Нативная сборка (native image) превращает приложение в обычный исполняемый файл для конкретной операционной системы — как программа на C или Go. JVM для запуска не нужна. Такую сборку делает инструмент native-image из GraalVM или его сборки для Quarkus — Mandrel. Quarkus изначально проектировали под нативную сборку, поэтому для большинства расширений она работает без доработок.
Jar или нативный файл
| Jar на JVM | Нативный файл | |
|---|---|---|
| Старт | Секунды | Десятки миллисекунд |
| Память после старта | Сотни МБ | Десятки МБ |
| Время сборки | Десятки секунд | Несколько минут |
| Пиковая скорость под нагрузкой | Выше благодаря JIT | Обычно ниже |
| Запуск | Нужна Java | Нужен только файл |
Нативный файл выгоден там, где сервис часто запускается и останавливается: serverless-функции, автомасштабирование в Kubernetes, маленькие контейнеры. Для долго работающего сервиса под постоянной нагрузкой обычный jar не хуже, а часто лучше.
Сборка с установленной GraalVM
Установите GraalVM для Java 25 (или Mandrel) и укажите путь к ней в переменной GRAALVM_HOME. В pom.xml генератор уже добавил профиль native, поэтому команда короткая:
./mvnw package -DnativeСборка идёт несколько минут и требует много памяти — лучше 8 ГБ свободной оперативной памяти. Результат — файл target/blog-1.0.0-SNAPSHOT-runner (в Windows — с расширением .exe), который запускается напрямую:
./target/blog-1.0.0-SNAPSHOT-runnerВ строке запуска вместо on JVM будет native, а время старта — в миллисекундах.
Сборка в контейнере
Если GraalVM ставить не хочется, но есть Docker или Podman, Quarkus соберёт файл внутри контейнера с Mandrel:
./mvnw package -Dnative -Dquarkus.native.container-build=trueУчтите: так получается исполняемый файл для Linux. Он подходит для Docker-образа (следующий урок), но не запустится напрямую в Windows или macOS.
Ограничения
native-image заранее анализирует, какой код достижим, и выбрасывает остальное. Поэтому то, что Java обычно делает во время работы, в нативном файле требует подсказок:
- Рефлексия. Классы, которые создаются или читаются через рефлексию в вашем коде, помечают
@RegisterForReflection. Сущности, ресурсы и записи для JSON Quarkus регистрирует сам. - Ресурсы. Файлы из
src/main/resources, которые читаются вручную, перечисляют вquarkus.native.resources.includes. - Библиотеки. Используйте расширения Quarkus вместо «голых» библиотек: расширение уже содержит нужные настройки для нативной сборки.
Нативную сборку проверяют тестами с @QuarkusIntegrationTest: генератор создавал GreetingResourceIT, и по его образцу можно сделать PostResourceIT extends PostResourceTest. Команда ./mvnw verify -Dnative соберёт файл и прогонит тесты прямо против него.
Частая ошибка
Если запустить -Dnative без GraalVM, сборка падает в самом конце:
[ERROR] Failed to execute goal io.quarkus.platform:quarkus-maven-plugin:3.40.1:build (default-build) on project blog:
Failed to build quarkus application: ... Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#build threw an exception:
java.lang.RuntimeException: Cannot find the `native-image.cmd` in the GRAALVM_HOME, JAVA_HOME and System PATH.
Это сообщение из Windows, где инструмент называется native-image.cmd. Установите GraalVM или Mandrel и задайте GRAALVM_HOME либо соберите в контейнере с -Dquarkus.native.container-build=true. В Windows для native-image дополнительно нужны инструменты сборки Visual Studio.