Статьи

Picocli в GraalVM: невероятно быстрые приложения для командной строки

GraalVM

GraalVM позволяет вам заблаговременно скомпилировать ваши программы в собственный исполняемый файл. Полученная программа имеет более быстрое время запуска и меньшие накладные расходы памяти времени выполнения по сравнению с виртуальной машиной Java. Это особенно полезно для утилит командной строки, которые часто бывают недолговечными.

GraalVM имеет ограниченную поддержку рефлексии Java, и ему необходимо заранее знать элементы программы с рефлексивным доступом.

Рефлексивный доступ

В настоящее время Picocli использует отражение для обнаружения классов и методов, аннотированных @Command , а также полей , методов или параметров методов, аннотированных @Option и @Parameters и других аннотаций picocli. В будущем выпуске Picocli может быть включен процессор аннотаций для выполнения этой работы во время компиляции, но в его нынешнем виде используется отражение.

Инструмент ReflectionConfigGenerator

Picocli 3.7.0 включает модуль picocli-codegen с инструментом, который генерирует файл конфигурации GraalVM.

ReflectionConfigGenerator генерирует строку JSON с элементами программы, которые будут рефлексивно доступны в приложении на основе picocli, чтобы заранее скомпилировать это приложение в собственный исполняемый файл с GraalVM.

Выходные данные ReflectionConfigGenerator предназначены для передачи в параметр -H:ReflectionConfigurationFiles=/path/to/reflectconfig для native-image . Это позволяет приложениям на основе picocli быть скомпилированными в собственное изображение.

Пример использования

В качестве picocli.codegen.aot.graalvm.Example мы будем использовать класс picocli.codegen.aot.graalvm.Example который находится в тестах для модуля picocli-codegen . Сначала мы сгенерируем reflect.json конфигурации reflect.json с помощью инструмента ReflectionConfigGenerator . Далее мы скомпилируем класс Example для нативного приложения, и, наконец, запустим это приложение и посмотрим, в чем разница во времени запуска нативного приложения и работы в Hotspot.

Генерация файла конфигурации

Запустите инструмент ReflectionConfigGenerator и укажите одно или несколько полных имен классов, @Command @Command. Вывод выводится в System.out , поэтому вы захотите перенаправить его в файл:

1
2
3
java -cp \
picocli-3.7.0.jar:picocli-codegen-3.7.0-tests.jar:picocli-codegen-3.7.0.jar \
picocli.codegen.aot.graalvm.ReflectionConfigGenerator picocli.codegen.aot.graalvm.Example > reflect.json

Сгенерированные reflect.json выглядят примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
[
  {
    "name" : "picocli.codegen.aot.graalvm.Example",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true,
    "fields" : [
        { "name" : "spec" },
        { "name" : "unmatched" },
        { "name" : "timeUnit" },
        { "name" : "file" }
    ],
    "methods" : [
        { "name" : "setMinimum", "parameterTypes" : ["int"] },
        { "name" : "setOtherFiles", "parameterTypes" : ["[Ljava.io.File;"] },
        { "name" : "multiply", "parameterTypes" : ["int", "int"] }
    ]
  },
...
]
Наконечник При необходимости можно исключить классы с системным свойством picocli.codegen.excludes , которое принимает разделенный запятыми список регулярных выражений полностью определенных имен классов, которые не должны включаться в результирующую строку JSON.

Компиляция родного изображения

Это предполагает, что у вас установлен GraalVM с предварительными условиями. С сайта :

Для создания собственного образа программы используйте утилиту native-image расположенную в каталоге bin дистрибутива GraalVM. Для компиляции native-image зависит от локальной цепочки инструментов, поэтому убедитесь, что в вашей системе доступны glibc-devel , zlib-devel (файлы заголовков для библиотеки C и zlib ) и gcc .

Мне также нужны статические пакеты glibc-static и zlib-static , кроме пакетов devel.

Мы скомпилируем пример класса с помощью следующей команды:

1
2
3
4
graalvm-ce-1.0.0-rc6/bin/native-image \
    -cp picocli-3.7.0.jar:picocli-codegen-3.7.0-tests.jar \
    -H:ReflectionConfigurationFiles=reflect.json -H:+ReportUnsupportedElementsAtRuntime \
    --static --no-server picocli.codegen.aot.graalvm.Example

reflect.json находится в текущем каталоге, и я добавил -H:+ReportUnsupportedElementsAtRuntime чтобы получить полезное сообщение об ошибке на случай, если что-то пойдет не так.

Наконечник native-image --expert-options показывает список других параметров компиляции, не показанных в выходных данных native-image --help .

Запуск собственного изображения

Если компиляция прошла успешно, у нас теперь есть собственный исполняемый файл picocli.codegen.aot.graalvm.example в текущем каталоге:

1
2
$ ls -alh picocli*
-rwxrwxr-x 1 remko remko 15M Oct  4 21:35 picocli.codegen.aot.graalvm.example

Имя исполняемого файла происходит от имени основного класса. Если jar является исполняемым jar (с Main-Class, указанным в манифесте), мы могли бы запустить native-image [options] -jar jarfile чтобы создать образ для файла jar.

Давайте сначала запустим приложение на Java, а затем посмотрим, сколько времени потребуется для его запуска.

1
2
3
4
5
6
7
$ time java -cp  picocli-3.7.0.jar:picocli-codegen-3.7.0-tests.jar \
    picocli.codegen.aot.graalvm.Example --version
3.7.0
 
real    0m0.492s
user    0m0.847s
sys     0m0.070s

В Java Hotspot для запуска требуется около полсекунды. Теперь запустим нативный образ:

1
2
3
4
5
6
$ time ./picocli.codegen.aot.graalvm.example --version
3.7.0
 
real    0m0.003s
user    0m0.000s
sys     0m0.004s

Время запуска теперь составляет до 3 миллисекунд!

Все функции синтаксического анализа командной строки работают должным образом, с преобразованием типов, проверкой и помощью с цветами ANSI. Это замечательная новость, когда вы хотите писать приложения и службы командной строки на Java и запускать их мгновенно.

Вывод

GraalVM — это потрясающая новая технология, которая позволяет программам на Java работать как собственный код. Это сокращает использование памяти и время запуска, что особенно полезно для коротких программ, таких как утилиты командной строки.

Инструмент ReflectionConfigGenerator , включенный в модуль picocli-codegen, позволяет компилировать приложения на основе picocli в собственные исполняемые файлы с чрезвычайно быстрым временем запуска.

Пожалуйста, пометьтеGraalVM и picocli на GitHub, если вам нравятся проекты!

Смотрите оригинальную статью здесь: Picocli на GraalVM: невероятно быстрые приложения для командной строки

Мнения, высказанные участниками Java Code Geeks, являются их собственными.