Отсутствуют компоненты среды выполнения JavaFX Maven Shade

Я пытаюсь создать JFX11 самодостаточную банку, используя зависимости maven. Судя по исследованиям, которые я сделал, кажется, что лучший способ сделать это - через плагин Maven Shade. Однако, когда я запускаю его, я получаю эту ошибку:

Ошибка: отсутствуют компоненты времени выполнения JavaFX, и они необходимы для запуска этого приложения

Я не понимаю, почему это происходит. Что я испортил? Есть лучший способ сделать это? Я также попробовал подключаемый модуль maven с тем же сообщением.

POM файл для справки

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>Application</groupId>
    <artifactId>Main</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>SpaceRunner</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <release>10</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>Application.Main</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>
                                Application.Main
                            </mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>Application.Main</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

1 ответ

Решение

Этот ответ объясняет, почему в JavaFX 11 произошел сбой в работе файла JAR-файла.

Эта ошибка происходит от sun.launcher.LauncherHelper в модуле java.base. Причина этого заключается в том, что приложение Main расширяет приложение и имеет метод main. Если это так, LauncherHelper проверит наличие javafx.graphics модуль должен присутствовать как именованный модуль. Если этот модуль отсутствует, запуск отменяется.

И уже предлагает исправить для Gradle.

Для Maven решение точно такое же: предоставить новый основной класс, который не расширяется от Application,

У вас будет новый класс в вашем application пакет (плохое имя):

// NewMain.java
public class NewMain {

    public static void main(String[] args) {
        Main.main(args);
    }
}

И ваши существующие Main класс, как есть:

//Main.java
public class Main extends Application {

    @Override
    public void start(Stage stage) {
        ...
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Теперь вам нужно изменить ваш pom и установить основной класс для различных плагинов:

<mainClass>application.NewMain</mainClass>

Жирная банка для конкретной платформы

Наконец, с помощью плагина Shade вы создадите толстую банку на своей машине.

Это означает, что пока ваши зависимости JavaFX используют уникальный классификатор. Например, если вы работаете в Windows, Maven будет использовать win классификатор. В результате включаются только собственные библиотеки для Windows.

Итак, вы используете:

  • org.openjfx: JavaFX-управления: 11
  • org.openjfx: JavaFX-управления:11: победа
  • org.openjfx: JavaFX-график: 11
  • org.openjfx: javafx-graphics:11: win <- содержит собственные библиотеки для Windows
  • org.openjfx: JavaFX-основа: 11
  • org.openjfx: JavaFX база:11: победа

Теперь, если вы создадите толстый флягу, вы скомпонуете все эти зависимости (и те другие обычные сторонние зависимости из вашего проекта), и вы сможете запустить свой проект как:

java -jar myFatJar-1.0-SNAPSHOT.jar

Хотя это очень хорошо, если вы хотите распространять свой jar, имейте в виду, что этот jar не кроссплатформенный, и он будет работать только на вашей платформе, в данном случае Windows.

Кроссплатформенная толстая банка

Существует решение для создания кроссплатформенного фляги, которую вы можете распространять: включайте остальные нативные библиотеки других платформ.

Это легко сделать, так как вам просто нужно включить зависимости графического модуля для трех платформ:

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>11</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics </artifactId>
        <version>11</version>
        <classifier>win</classifier>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics </artifactId>
        <version>11</version>
        <classifier>linux</classifier>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics </artifactId>
        <version>11</version>
        <classifier>mac</classifier>
    </dependency>
</dependencies>

Размер

С этим подходом связана основная проблема: размер. Как вы можете видеть в этом другом ответе, если вы используете элемент управления WebView, вы будете упаковывать около 220 МБ из-за собственных библиотек WebKit.

Другие вопросы по тегам