有一个依赖项很大的项目(我使用 helidon)。从 IDEA 运行时,一切正常。通过mvn package
和后续的组装项目java -jar myproject.jar
,各种错误开始爬出来。据我了解,由于依赖项中的某些类没有进入生成的 jar(或者类加载器找不到它们,因为我似乎在 jar 文件中看到它们),因此出现了错误。
在指定不同的依赖项时,例如不同的版本或不同的包,会丢失不同的类。
例如,yaml 配置解析器现在没有加载。虽然文件YamlConfigParser.class
在 jar 文件中
在 IDEA 中,我显然没有规定任何依赖项和设置。一切都在 pom.xml
问题是发生了什么,不同的行为从何而来?
顺便说一句,还是有构建jar,但是IDEA无法编译项目的情况。说没有找到课程。
我不知道这是否与主题有关,但是在构建maven时,出现一堆消息
[警告] 发现 module-info.class。着色会破坏其强大的封装。
构建由 maven-shade-plugin 完成
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.Loader</mainClass>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
</build>
如果 jar 文件是通过 Build Artifacts 在 IDEA 中创建的,那么一切正常。
比较了来自 IDEA 和 maven 的两个 jar 文件。课程是一样的。在 IDEA 的版本中,module-info.class 位于根目录,META-INF 文件夹的内容非常不同
发现了问题。依赖库大量使用 ServiceLoader 和动态类加载。有关要加载的类的信息被添加到 META-INF/services 文件夹中的文件中。
默认情况下,maven-shade-plugin 将依赖模块的 META-INF/services 中的第一个可用文件放入最终的 jar 中。但是如果你为插件指定一个转换器
org.apache.maven.plugins.shade.resource.ServicesResourceTransformer
然后当在 META-INF/services 文件夹中的依赖模块中找到具有相同名称的文件时,所有这些文件将合并到最终的 jar 中,并且所有类都将在运行时找到。