如何防止maven-shade-plugin暴露<system>范围依赖?
我之前也踩过几乎一模一样的坑!用maven-shade-plugin构建uber-jar时,system范围的依赖很容易在生成dependency-reduced pom时“偷偷跑进去”,尤其是像tools.jar这种依赖本地路径的家伙,泄露出去之后绝对会给后续依赖这个pom的项目添乱。
先给你拆解下问题根源:maven-shade-plugin生成dependency-reduced pom的逻辑默认会包含所有依赖,不管它的scope是什么。而你的tools.jar是通过java.home定位的本地文件,其他机器的JDK路径、版本可能完全不同,甚至JDK9+里根本就没有tools.jar了,这依赖一旦泄露出去,依赖方构建时大概率会报错。
下面是我亲测有效的解决步骤:
1. 给maven-shade-plugin加配置,明确排除system依赖
在插件的configuration里添加<dependencyReducedPomExcludes>节点,指定tools.jar的坐标,让它别出现在dependency-reduced pom里:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <!-- 替换成你正在使用的插件版本 --> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <!-- 保留你原本的ServiceLoader转换器配置 --> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <!-- 重点:排除system范围的tools.jar --> <dependencyReducedPomExcludes> <exclude>com.sun:tools</exclude> </dependencyReducedPomExcludes> </configuration> </execution> </executions> </plugin>
2. 优化tools.jar的依赖配置,从源头减少传递风险
确保你pom里的tools.jar依赖明确标记为optional=true,进一步降低它被意外传递的可能性:
<dependency> <groupId>com.sun</groupId> <artifactId>tools</artifactId> <version>${java.version}</version> <scope>system</scope> <systemPath>${java.home}/../lib/tools.jar</systemPath> <optional>true</optional> <!-- 加上这个,避免依赖传递 --> </dependency>
3. 验证结果
运行mvn clean package之后,去target目录下找到生成的dependency-reduced-pom.xml,打开检查确认里面已经没有tools.jar的依赖项了。同时测试你的uber-jar是否能正常启动,确保ServiceLoader的合并功能没有受到影响。
另外提个额外建议:如果你的项目已经升级到JDK9+,其实完全可以抛弃tools.jar的依赖——JDK9把tools.jar的内容拆分成了模块化组件,你只需要在编译配置里添加--add-modules jdk.compiler这类参数,就能解决编译期的依赖需求,彻底避开system依赖带来的各种麻烦。
内容的提问来源于stack exchange,提问作者Kyle Moore

