Пакет #getImplementationVersion() возвращает null с собственным изображением (GraalVM/GluonFX)

У меня есть настольное приложение на основе JavaFX, для которого я создаю собственные образы с помощью GraalVM / GluonFX. Чтобы получить версию приложения во время выполнения, я ранее - когда был только толстый JAR приложения - использовал. Однако это возвращает null.

Я полагаю, это потому, что я неправильно установил записи манифеста? Моя конфигурация gluonfx-maven-plugin:

      <plugin>
    <groupId>com.gluonhq</groupId>
    <artifactId>gluonfx-maven-plugin</artifactId>
    <version>1.0.10</version>
    <configuration>
        <mainClass>${mainClass}</mainClass>
        <nativeImageArgs>
            <arg>--allow-incomplete-classpath</arg>
            <arg>--initialize-at-build-time=org.pdfclown.Version</arg>
            <arg>--no-fallback</arg>
        </nativeImageArgs>
    </configuration>
</plugin>

Есть ли способ настроить плагин так, чтобы Package#getImplementationVersion()возвращает версию приложения? Мне не удалось найти что-то в соответствующей документации . Кроме того, в 2020 году была решена с связаннаяэтим проблема в GraalVM.

1 ответ

Допустим, у вас есть проект Maven, и вы добавляете в свой основной класс приложения:

      @Override
public void start(Stage primaryStage) throws Exception {
    ...
    System.out.println("Main class version: " + getClass().getPackage().getImplementationVersion());
}

Если вы сделаете толстую банку с плагином тени и позаботитесь о добавлении необходимых записей манифеста, таких как (скажем, 1.0), когда вы запускаете:

      java --module-path=PATH_TO_FX --add-modules javafx.controls,javafx.fxml -jar my-fat-jar.jar

он должен печатать:

      Main class version: 1.0

Однако если вы запустите

      mvn javafx:run

он печатает:

      Main class version: null

как вы сообщили.

Причина этого: в пути к классам нет манифеста, а классы ( target/classes) не упакованы в банку.

Если ваш проект имеет стороннюю зависимость, которая включает манифест с Implementation-Versionвход (скажем 2.0), делает:

      @Override
public void start(Stage primaryStage) throws Exception {
    ...
    System.out.println("3rd party Main class version: " + com.my.third.party.MainClass.class.getPackage().getImplementationVersion());
}

заработает:

      mvn javafx:run
[INFO] --- javafx-maven-plugin:0.0.8:run (default-cli) @ MyProject ---
3rd party Main class version: 2.0.

потому что банка является зависимостью упакованных классов с манифестом.

И делаем нативный образ mvn gluonfx:build gluonfx:nativerunтакже работает:

      [INFO] --- gluonfx-maven-plugin:1.0.10:nativerun (default-cli) @ MyProject ---
[Mon Dec 20 21:29:16 CET 2021][INFO] ==================== RUN TASK ====================
[Mon Dec 20 21:29:16 CET 2021][INFO] [SUB] 2021-12-20 21:29:16.810 MyProject[23068:414510] Starting Gluon VM...
[Mon Dec 20 21:29:16 CET 2021][INFO] [SUB] Dec 20, 2021 9:29:16 PM com.sun.javafx.application.PlatformImpl startup
[Mon Dec 20 21:29:16 CET 2021][INFO] [SUB] WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @21c815e4'
[Mon Dec 20 21:29:16 CET 2021][INFO] [SUB] 3rd party Main class version: 2.0

Итак, на данный момент я вижу три варианта:

  • Переместите свой основной код в модуль, опубликуйте банку и добавьте ее в свой основной проект в качестве зависимости, это должно работать.
  • Переместите пары "ключ-значение" манифеста в файл свойств и используйте подключаемый модуль ресурсов Maven. Это должно работать из коробки с плагином GluonFX (убедитесь, что вы добавили расширение свойств в список ресурсов). Это должно быть самым простым.
  • Сообщите о проблеме на Substrate, чтобы запросить манифест. Пока что Substrate создает jar из классов проекта , так что теоретически у него тоже может быть манифест, и в него можно было бы занести какие-то ключи-значения, исходящие из конфигурации плагина. Добавить манифест легко, проблема заключается в добавлении изменений в конфигурацию для передачи ключей-значений.
Другие вопросы по тегам