使用 Moditect 将模块信息添加到现有的 Maven 依赖项

Con*_*nor 6 java jlink maven moditect

我正在使用 JavaFX,并且有一些不是自动模块的依赖项。当尝试运行时,mvn clean javafx:jlink我收到以下错误:

Error: automatic module cannot be used with jlink: org.apache.commons.io from [...]`
Run Code Online (Sandbox Code Playgroud)

这对于org.apache.commons.commons-lang3和也产生了错误commons-codec.commons-codec。我看到的错误是随机的。

所以我研究使用 jdeps 来生成依赖项的模块信息,例如

jdeps --generate-module-info tmp .../.m2/repository/commons-io/commons-io/2.12.0/commons-io-2.12.0.jar
Run Code Online (Sandbox Code Playgroud)

然后我使用 Moditect 将模块信息添加到现有的 jar 中:

Error: automatic module cannot be used with jlink: org.apache.commons.io from [...]`
Run Code Online (Sandbox Code Playgroud)

但我仍然遇到同样的错误。

我的模块信息:

jdeps --generate-module-info tmp .../.m2/repository/commons-io/commons-io/2.12.0/commons-io-2.12.0.jar
Run Code Online (Sandbox Code Playgroud)

我的完整 pom.xml:

<plugin>
    <groupId>org.moditect</groupId>
    <artifactId>moditect-maven-plugin</artifactId>
    <version>1.0.0.Final</version>
    <executions>
        <execution>
            <id>add-module-infos</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>add-module-info</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/modules</outputDirectory>
                <modules>
                    <module>
                        <artifact>
                            <groupId>commons-io</groupId>
                            <artifactId>commons-io</artifactId>
                            <version>2.12.0</version>
                        </artifact>
                        <moduleInfoSource>
                            module org.apache.commons.io {
                                exports org.apache.commons.io;
                                exports org.apache.commons.io.build;
                                exports org.apache.commons.io.charset;
                                exports org.apache.commons.io.comparator;
                                exports org.apache.commons.io.file;
                                exports org.apache.commons.io.file.attribute;
                                exports org.apache.commons.io.file.spi;
                                exports org.apache.commons.io.filefilter;
                                exports org.apache.commons.io.function;
                                exports org.apache.commons.io.input;
                                exports org.apache.commons.io.input.buffer;
                                exports org.apache.commons.io.monitor;
                                exports org.apache.commons.io.output;
                                exports org.apache.commons.io.serialization;
                            }
                        </moduleInfoSource>
                    </module>
                    <module>
                        <artifact>
                            <groupId>org.apache.commons</groupId>
                            <artifactId>commons-lang3</artifactId>
                            <version>3.12.0</version>
                        </artifact>
                        <moduleInfoSource>
                            module org.apache.commons.lang3 {
                                requires transitive java.desktop;

                                exports org.apache.commons.lang3;
                                exports org.apache.commons.lang3.arch;
                                exports org.apache.commons.lang3.builder;
                                exports org.apache.commons.lang3.compare;
                                exports org.apache.commons.lang3.concurrent;
                                exports org.apache.commons.lang3.concurrent.locks;
                                exports org.apache.commons.lang3.event;
                                exports org.apache.commons.lang3.exception;
                                exports org.apache.commons.lang3.function;
                                exports org.apache.commons.lang3.math;
                                exports org.apache.commons.lang3.mutable;
                                exports org.apache.commons.lang3.reflect;
                                exports org.apache.commons.lang3.stream;
                                exports org.apache.commons.lang3.text;
                                exports org.apache.commons.lang3.text.translate;
                                exports org.apache.commons.lang3.time;
                                exports org.apache.commons.lang3.tuple;
                            }
                        </moduleInfoSource>
                    </module>
                    <module>
                        <artifact>
                            <groupId>commons-codec</groupId>
                            <artifactId>commons-codec</artifactId>
                            <version>1.15</version>
                        </artifact>
                        <moduleInfoSource>
                            module org.apache.commons.codec {
                                exports org.apache.commons.codec;
                                exports org.apache.commons.codec.binary;
                                exports org.apache.commons.codec.cli;
                                exports org.apache.commons.codec.digest;
                                exports org.apache.commons.codec.language;
                                exports org.apache.commons.codec.language.bm;
                                exports org.apache.commons.codec.net;
                            }
                        </moduleInfoSource>
                    </module>
                </modules>
            </configuration>
        </execution>
    </executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)

我还运行mvn dependency:tree生成以下内容:

[INFO] uk.co.conoregan.show-renamer:show-renamer:jar:1.4.0
[INFO] +- org.slf4j:slf4j-api:jar:2.0.7:compile
[INFO] +- org.slf4j:slf4j-simple:jar:2.0.7:runtime
[INFO] +- org.junit.jupiter:junit-jupiter-api:jar:5.9.3:test
[INFO] |  +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] |  +- org.junit.platform:junit-platform-commons:jar:1.9.3:test
[INFO] |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.9.3:test
[INFO] |  \- org.junit.platform:junit-platform-engine:jar:1.9.3:test
[INFO] +- org.mockito:mockito-core:jar:5.3.1:test
[INFO] |  +- net.bytebuddy:byte-buddy:jar:1.14.4:test
[INFO] |  +- net.bytebuddy:byte-buddy-agent:jar:1.14.4:test
[INFO] |  \- org.objenesis:objenesis:jar:3.3:test
[INFO] +- org.openjfx:javafx-controls:jar:20.0.1:compile
[INFO] |  +- org.openjfx:javafx-controls:jar:win:20.0.1:compile
[INFO] |  \- org.openjfx:javafx-graphics:jar:20.0.1:compile
[INFO] |     +- org.openjfx:javafx-graphics:jar:win:20.0.1:compile
[INFO] |     \- org.openjfx:javafx-base:jar:20.0.1:compile
[INFO] |        \- org.openjfx:javafx-base:jar:win:20.0.1:compile
[INFO] +- org.openjfx:javaf

Ian*_*ang 1

问题

  • JLink 不适用于自动模块(即没有 module-info.java 文件的包)

脚步

使用maven-dependency-plugin将依赖项复制到 {build_folder}/dependency

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.6.0</version>
    <executions>
        <execution>
            <id>copy</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)

使用moditect-maven-plugin添加自动模块的模块信息

<plugin>
    <groupId>org.moditect</groupId>
    <artifactId>moditect-maven-plugin</artifactId>
    <version>1.0.0.Final</version>
    <executions>
        <execution>
            <id>add-module-infos</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>add-module-info</goal>
            </goals>
            <configuration>
                <outputDirectory>
                    ${project.build.directory}/dependency
                </outputDirectory>
                <modules>
                    <module>
                        <artifact>
                            <groupId>commons-io</groupId>
                            <artifactId>commons-io</artifactId>
                            <version>2.13.0</version>
                        </artifact>
                        <moduleInfoSource>
                            module org.apache.commons.io {
                            exports org.apache.commons.io;
                            exports org.apache.commons.io.build;
                            exports org.apache.commons.io.charset;
                            exports org.apache.commons.io.comparator;
                            exports org.apache.commons.io.file;
                            exports org.apache.commons.io.file.attribute;
                            exports org.apache.commons.io.file.spi;
                            exports org.apache.commons.io.filefilter;
                            exports org.apache.commons.io.function;
                            exports org.apache.commons.io.input;
                            exports org.apache.commons.io.input.buffer;
                            exports org.apache.commons.io.monitor;
                            exports org.apache.commons.io.output;
                            exports org.apache.commons.io.serialization;

                            }

                        </moduleInfoSource>
                    </module>
                </modules>
                <overwriteExistingFiles>true</overwriteExistingFiles>
            </configuration>
        </execution>

    </executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)

如何获取<moduleInfoSource>内容?

  • 转到包含所需(依赖项).jar 文件的文件夹
  • 如果您使用 Intellij IDEA,在项目视图中,会有一个名为External Libraries. 双击该条目,右键单击.jar,在 -> 资源管理器中打开。
  • 在该文件夹中打开命令提示符
  • jdeps -generate-module-info . {jar_file_name}.jar
  • 确保PATH环境变量正确
  • 打开生成的module-info.java文件并复制内容
  • 粘贴到该<moduleInfoSource>部分

创建运行时映像(使用 jlink,在后端)

  • 请更改<modules>,<launcher>请根据您的项目信息
  • 如果您的模块是非模块化的,那么主类不要javafx.Application直接扩展,这一点很重要。我们可以创建一个如下所示的启动器类(参考待定):

发射器类

public class Launcher {  
    public static void main(String[] args) {  
        HelloApplication.main(args);  
    }  
}
Run Code Online (Sandbox Code Playgroud)

pom.xml

<execution>
    <id>create-runtime-image</id>
    <phase>package</phase>
    <goals>
        <goal>create-runtime-image</goal>
    </goals>
    <configuration>
        <jarInclusionPolicy>APP_WITH_DEPENDENCIES</jarInclusionPolicy>
        <modulePath>
            <path>${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging}</path>
            <path>${project.build.directory}/dependency</path>
        </modulePath>
        <modules>
            <module>com.example.soone</module>
        </modules>
        <launcher>
            <name>hello</name>
            <module>com.example.soone/com.example.soone.Launcher</module>
        </launcher>
        <outputDirectory>
            ${project.build.directory}/jlink-image
        </outputDirectory>
    </configuration>
</execution>
Run Code Online (Sandbox Code Playgroud)

链接到演示存储库

推荐

  • 我建议将构建系统更改为 Gradle,它与自动模块配合使用效果更好,并且您无需手动找出依赖项,可以节省大量时间,尤其是在使用 JavaFX 时。