Maven Shade JavaFX runtime components are missing

后端 未结 1 796
日久生厌
日久生厌 2020-11-22 06:12

I\'m trying to create a JFX11 self-containing jar using maven dependencies. From the research I\'ve done, it seems the best way to do this is through the maven shade plugin.

相关标签:
1条回答
  • 2020-11-22 06:45

    This answer explains why a fat/uber jar fails on JavaFX 11. In short:

    This error comes from sun.launcher.LauncherHelper in the java.base module. The reason for this is that the Main app extends Application and has a main method. If that is the case, the LauncherHelper will check for the javafx.graphics module to be present as a named module. If that module is not present, the launch is aborted.

    And already proposes a fix for Gradle.

    For Maven the solution is exactly the same: provide a new main class that doesn't extend from Application.

    You will have new class in your application package (bad name):

    // NewMain.java
    public class NewMain {
    
        public static void main(String[] args) {
            Main.main(args);
        }
    }
    

    And your existing Main class, as is:

    //Main.java
    public class Main extends Application {
    
        @Override
        public void start(Stage stage) {
            ...
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    Now you need to modify your pom and set your main class for the different plugins:

    <mainClass>application.NewMain</mainClass>
    

    Platform-specific Fat jar

    Finally, with the shade plugin you are going to produce a fat jar, on your machine.

    This means that, so far, your JavaFX dependencies are using a unique classifier. If for instance you are on Windows, Maven will be using internally the win classifier. This has the effect of including only the native libraries for Windows.

    So you are using:

    • org.openjfx:javafx-controls:11
    • org.openjfx:javafx-controls:11:win
    • org.openjfx:javafx-graphics:11
    • org.openjfx:javafx-graphics:11:win <-- this contains the native dlls for Windows
    • org.openjfx:javafx-base:11
    • org.openjfx:javafx-base:11:win

    Now, if you produce the fat jar, you will bundle all those dependencies (and those other regular third party dependencies from your project), and you will be able to run your project as:

    java -jar myFatJar-1.0-SNAPSHOT.jar
    

    While this is very nice, if you want to distribute you jar, be aware that this jar is not cross-platform, and it will work only on your platform, in this case Windows.

    Cross-Platform Fat Jar

    There is a solution to generate a cross-platform jar that you can distribute: include the rest of the native libraries of the other platforms.

    This can be easily done, as you just need to include the graphics module dependencies for the three platforms:

    <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>
    

    Size

    There is a main issue with this approach: the size. As you can see in this other answer, if you use the WebView control, you will be bundling around 220 MB due to the WebKit native libraries.

    0 讨论(0)
提交回复
热议问题