【问题标题】:Is there a way to add maven dependencies while using the maven-jlink-plugin?有没有办法在使用 maven-jlink-plugin 时添加 maven 依赖项?
【发布时间】:2018-04-16 15:00:35
【问题描述】:

我正在使用这个Github project 来接触Java 9 中的新模块化功能。我想向项目添加依赖项并能够构建本机映像。但是,当我尝试向 pom.xml 添加新的依赖项并将 requires 语句添加到 module-info.java 时,我从 maven-jlink-plugin 收到以下错误:

Error: module-info.class not found for joda.time module

我正在尝试将此作为概念证明,即我可以使用新的链接阶段部署图像,但自然我需要能够拥有外部依赖项并且我需要使用 maven(工作约束)。

对 mod-jar/pom.xml 的更改

...
 <dependencies>
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.9.9</version>
    </dependency>
  </dependencies>
...

mod-jar/module-info.java

module com.soebes.nine.jar {
  requires java.base;
  requires joda.time;
  exports com.soebes.example.nine.jar;
}

日志:

[INFO] --- maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) @ mod-jlink ---
[INFO] Toolchain in maven-jlink-plugin: jlink [ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jlink ]
[INFO] The following dependencies will be linked into the runtime image:
[INFO]  -> module: com.soebes.nine.one ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-1/target/jmods/com.soebes.nine.one.jmod )
[INFO]  -> module: com.soebes.nine.two ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-2/target/jmods/com.soebes.nine.two.jmod )
[INFO]  -> module: com.soebes.nine.jar ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-jar/target/com.soebes.nine.jar-1.0-SNAPSHOT.jar )
[INFO]  -> module: joda.time ( /Users/sebastianrestrepo/.m2/repository/joda-time/joda-time/2.9.9/joda-time-2.9.9.jar )
[ERROR] 
Error: module-info.class not found for joda.time module
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] parent ............................................. SUCCESS [  1.460 s]
[INFO] com.soebes.nine.one ................................ SUCCESS [  2.022 s]
[INFO] com.soebes.nine.two ................................ SUCCESS [  1.392 s]
[INFO] com.soebes.nine.jar ................................ SUCCESS [  1.388 s]
[INFO] mod-jlink .......................................... FAILURE [  1.061 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.911 s
[INFO] Finished at: 2017-11-03T15:27:35-04:00
[INFO] Final Memory: 26M/981M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) on project mod-jlink: 

我非常感谢任何帮助。谢谢。

【问题讨论】:

  • 日志来自在 maven-example 目录中运行 mvn clean package

标签: java maven jodatime java-9 jlink


【解决方案1】:

这里有not much to do with the plugin I believe。在您的情况下,模块joda.time 似乎是一个自动模块

jlink tool does not support linking of automatic modules 因为它们可以依赖于类路径的任意内容,这与自包含 Java 运行时的想法背道而驰。

所以可能有两种方法可以解决这个问题:-

  • (你不拥有 jar)暂时继续创建一个module-info.java[你可以为它使用use jdeps tool] 并使用相应的编译类更新 jar[使用jar 工具] Java 9 下的项目。

  • (您拥有依赖项)将 jar 永久迁移到 Java 9 本身,在编译和打包后它将由 module-info.class 本身组成。

【讨论】:

  • 虽然我会等待你克隆的 repo 的所有者提出他已经尝试克服的问题。 @khmarbaise
  • 感谢您的快速回复。我在将 module-info.java 添加到现有 jar 时遇到了一些问题。我可以将 java 文件添加到 jar 中,但我认为我需要它是一个 .class 文件。但是,我似乎无法编译 module-info.java 文件,因为编译器说 org.joda.time 不存在。有什么建议吗?
  • 为了编译module-info.java,你需要将JAR的内容解压到一个目录。然后编译 module-info.java 并将输出目录 (-d) 设置为您提取内容的目录。对你不维护的 JAR 文件这样做当然有点不酷,最好让库的维护者将其迁移到显式模块。
  • Joda-Time 会在某个时候添加一个 module-info.class,你只需要留意发布。模块名称为org.joda.time
  • 不幸的是,您必须等待包含 module-info.java 文件的 Joda-Time 发布......
【解决方案2】:

您可以使用ModiTect Maven plug-in 将模块描述符添加到 JAR 并使用该模块创建模块化运行时映像。

免责声明:我是 ModiTect 的作者。

【讨论】:

  • +1 for Moditect:允许无法迁移到 JDK 9+ 的库仍然可以很好地生成有效的模块信息,尤其是。来自 Maven。
【解决方案3】:

让我试着解释一下这方面的技术背景:

问题中给出的版本 2.9.9 中的 joda-time 是一个非模块化 jar,它不包含 module-info.class,并且它没有使用 Automatic-Module- 将自己声明为自动模块名称:在其 META-INF/MANIFEST.MF 中

真实模块中的类不能调用类路径上的类,因此您不能在该版本的模块信息中使用“requires jode.time”。

自动模块可以使用 ClassPath 上的类。为了在真实模块中使用非模块化 jar 中的类,您可以使用本身是自动模块的包装器。

到现在为止,存在 joda-time 的 2.10.1 版本,它是一个自动模块并声明“自动模块名称:org.joda.time”,因此您可以使用“需要 org.joda.time " 在您的真实模块中使用该新版本。

现在新的 jlink 工具不能直接使用非模块化 jars 或自动 jars 操作,maven-jlink 插件目前基本上只是 jlink 工具的 maven 包装器,将其配置参数转换为 jlink 工具的参数。

为了使用混合 maven 依赖项与真实模块、自动模块和非模块化 jar 的项目创建自定义 Java 运行时,您必须了解真实模块、自动模块和非模块化 jar 的所有系统模块依赖关系而不是使用 --add-modules 参数与这些进行 jlink。

要收集系统模块依赖项,您可以使用带有 --print-module-deps 或 --list-deps 参数的新 jdeps 工具,具体取决于所使用的实际 JDK 版本。

如果您将 maven 用于您的项目,您可以通过创建或使用为您执行此操作的 maven 插件来自动执行该任务。

【讨论】:

    【解决方案4】:

    我在我的一个项目中遇到了类似的问题。首先,我尝试了moditect-maven-plugin,效果很好!但是,使用此插件,您必须单独配置缺少模块描述符的每个依赖项。 如果您有许多依赖项缺少模块描述符,这可能会很麻烦。

    因此,我决定开发一个新的 maven 插件,jigsaw-maven-plugin(参见https://github.com/ghackenberg/jigsaw-maven-plugin)。 插件提供了三个目标,用于修补所有未命名的模块(参见步骤 3)以及链接和打包这些模块(参见步骤 4 和 5)

    在修补、链接和打包之前,您需要在其中构建项目 JAR(参见步骤 1)并将项目依赖项(参见步骤 2)复制到一个公共位置(例如 ${project.build.directory}/modules )。也许您可以使用以下构建插件配置来开始使用(更多详细信息请参阅GitHub page):

    第 1 步:构建存档

    <plugin>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.2.0</version>
      <configuration>
        <outputDirectory>${project.build.directory}/modules</outputDirectory>
      </configuration>
    </plugin>
    

    第 2 步:复制依赖项

    <plugin>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>3.2.0</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>copy-dependencies</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/modules</outputDirectory> 
          </configuration>
        </execution>
      </executions>
    </plugin>
    

    第 3 步:修补所有未命名的模块

    modulePath 中搜索缺少模块描述符的JAR,使用jdepsjavac 生成缺少的模块描述符,并使用java.util.zip 将它们添加到各自的JAR。

    <plugin>
      <groupId>io.github.ghackenberg</groupId>
      <artifactId>jigsaw-maven-plugin</artifactId>
      <version>1.1.0</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>patch</goal>
          </goals>
          <configuration>
            <modulePath>${project.build.directory}/modules</modulePath>
          </configuration>
        </execution>
      </executions>
    </plugin>
    

    第 4 步:链接模块

    使用jlink链接模块。

    <plugin>
      <groupId>io.github.ghackenberg</groupId>
      <artifactId>jigsaw-maven-plugin</artifactId>
      <version>1.1.0</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>link</goal>
          </goals>
          <configuration>
            <modulePath>${project.build.directory}/modules</modulePath>
            <module>your.module.name</module>
            <output>${project.build.directory}/image</output>
          </configuration>
        </execution>
      </executions>
    </plugin>
    

    第 5 步:打包模块

    使用jpackage封装模块。

    <plugin>
      <groupId>io.github.ghackenberg</groupId>
      <artifactId>jigsaw-maven-plugin</artifactId>
      <version>1.1.0</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>package</goal>
          </goals>
          <configuration>
            <modulePath>${project.build.directory}/modules</modulePath>
            <runtimeImage>${project.build.directory}/image</runtimeImage>
            <mainClass>your.module.name/your.package.Main</mainClass>
          </configuration>
        </execution>
      </executions>
    </plugin>
    

    【讨论】:

      猜你喜欢
      • 2019-12-27
      • 2010-11-28
      • 2011-06-10
      • 2015-07-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      相关资源
      最近更新 更多