ClassLoader.getResources()在module-path可用,jlink中失效,是否为JDK Bug?
问题:jlink构建后ClassLoader.getResources()无法找到资源是否属于JDK Bug?
在以下测试场景中,调用ClassLoader.getResources("database/migration"):
- 直接通过module-path运行时,返回1条结果(符合预期)
- 经过jlink构建自定义运行时后,返回0条结果(不符合预期)
测试用例详情
模块定义(src/main/java/module-info.java)
module jlink.testcase { opens database.migration; }
主类代码(src/main/java/testcase/Main.java)
package testcase; import java.io.IOException; import java.net.URL; import java.util.Collections; import java.util.List; public class Main { public static void main(String[] args) throws IOException { List<URL> resources = Collections.list(Main.class.getClassLoader().getResources("database/migration")); System.out.println("Found: " + resources); } }
资源文件
src/main/resources/database/migration/V1__placeholder.sql(空文件)
Maven配置(pom.xml)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>jlink-testcase</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.release>20</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> <mainClass>testcase.Main</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> </project>
测试脚本
正常运行脚本(good.bat)
@echo off java -ea --module-path "%JAVA_HOME%\bin\jmods;target\jlink-testcase-1.0-SNAPSHOT.jar" --module jlink.testcase
jlink构建后运行脚本(bad.bat)
@echo off rd /s /q target\jlink set JDK_JAVA_OPTIONS=-ea jlink --add-modules jlink.testcase --module-path "%JAVA_HOME%\bin\jmods;target\jlink-testcase-1.0-SNAPSHOT.jar" --output target\jlink --launcher testcase=jlink.testcase target\jlink\bin\java --module-path target\jlink-resources-1.0-SNAPSHOT.jar --module jlink.testcase
结论:这不是JDK Bug,而是使用方式错误
问题出在bad.bat的最后一行:你在jlink构建的运行时中额外指定了--module-path target\jlink-resources-1.0-SNAPSHOT.jar,但该jar包并不存在(项目构建产物为jlink-testcase-1.0-SNAPSHOT.jar)。同时jlink已经将jlink.testcase模块打包进自定义运行时,此时指定的module-path会覆盖默认模块路径,导致运行时找不到原本包含资源的模块。
修复方式
修改bad.bat的最后一行,去掉多余的--module-path参数,直接运行:
target\jlink\bin\java --module jlink.testcase
若确实需要加载额外模块,确保module-path指向正确的jar包即可。
另外需要注意:jlink构建的自定义运行时已将目标模块整合到镜像中,默认无需再指定module-path,除非要添加镜像外的额外模块。
内容的提问来源于stack exchange,提问作者Gili
相关产品推荐
相关产品推荐

