如何使用非模块化依赖项在Java 11上打包应用程序

问题描述 投票:4回答:2

我开发并分发了一个使用Apache Batik和JavaCV的Java Swing应用程序。我已经通过java 1.6,7和8更新了它。用于macOS,Windows和Linux的安装程序是使用Javapackager构建的。 Java 8在19年1月停止支持,我找不到在Java 11(新的LTS版本)上打包和分发的解决方案。

JavaCV或Batik都没有生产模块化jar,但是我已经设法将它们重新打包到我可以在Java 11上编译和生成可运行的jar的程度,app工作正常,但我无法将其打包以进行分发。我计划在Java 10中使用javapackager并从那里捆绑11运行时但它使用jlink生成自定义运行时,jlink失败,因为JavaCV和Batik不是模块化的。由于Batik和JavaCV中的引用不满意,jdeps不会生成要修补的模块-info.class并使它们模块化,即使我的应用程序在没有它们的情况下工作正常。

因此,我将不得不将代码库保留在Java 8中,即使不再支持它也可以发送它。

我知道有一个调用来创建javapackager的替换,但是在Java 8被弃用之后才会出现这种情况。我仍然需要Batik和JavaCV项目来重构和构建模块化jar以生成自定义运行时。

有人可以提供任何其他解决方案吗?我错过了什么吗?谢谢。

java java-11 jlink javapackager jdeps
2个回答
4
投票

我有同样的问题。我想使用JDK 11,但根据JDK-8212780,JEP 343计划用于JDK 13,所以我们需要等待一段时间。在Java 8-10下打包“本机”自包含应用程序不是问题,因为打包器被包含在内(至少在Oracle JDK中)。

今天我发现了关于this email的问题,并想知道我想尝试一下:你可以在github.com/skymatic/javafx11-test上看到我的示例项目,我使用来自JDK开发分支的后端移植的jpackager成功打包。

我在这里做了什么:

  • 使用OpenJDK 11和OpenJFX 11创建了一个新的HelloWorld项目。
  • 下载打包器并从Maven构建中调用它(注意它需要驻留在JDK中,你需要设置JAVA_HOME才能使它工作......)
  • 奖励:我使用jdeps找出我的非模块化jar的依赖关系并设置--add-modules参数以生成更小的运行时映像

当然,模块化项目更容易:在this commit to my sample project中你可以看到我使用jpackager的参数作为模块路径和主模块而不是类路径和主类。


0
投票

因此,唯一的解决方案是编写一个使用ProcessBuilder启动原始应用程序jar的包装器应用程序。

这方面的优点是链接可用于产生最小的所需运行时间。将jar放在bin目录中,然后使用FPM(https://github.com/jordansissel/fpm)创建安装程序。

包装器的示例代码

package xyz.arwhite.dslauncher;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class DrumScoreLauncher {

    public static void main(String[] args) {
        String installHome = System.getProperty("java.home");
        String installBin = installHome + File.separator + "bin" + File.separator;

        System.out.println("Launching Drum Score Editor from "+installHome);

        List<String> cmdLine = new ArrayList<String>();
        cmdLine.add(installBin + "java");
        cmdLine.add("-jar");
        cmdLine.add(installBin + "DrumScoreEditor.jar");

        for ( int i = 0; i < args.length; i++ )
            cmdLine.add(args[i]);

        try {
            ProcessBuilder p = new ProcessBuilder(cmdLine);
            p.inheritIO();
            p.start();

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Exiting launcher");
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.