Gradle重复包排除问题:解决jOpenDocument与java.xml的org.w3c.dom冲突
问题描述
使用Gradle构建项目,依赖JavaFX、Maven仓库的log4j,以及本地flatDir目录中的jOpenDocument-1.5包。在JDK19环境下构建时出现以下错误:
error: the unnamed module reads package org.w3c.dom from both jOpenDocument and java.xml error: module javafx.graphicsEmpty reads package org.w3c.dom from both jOpenDocument and java.xml error: module javafx.baseEmpty reads package org.w3c.dom from both jOpenDocument and java.xml error: module org.apache.logging.log4j.core reads package org.w3c.dom from both jOpenDocument and java.xml error: module javafx.controlsEmpty reads package org.w3c.dom from both jOpenDocument and java.xml error: module jOpenDocument reads package org.w3c.dom from both java.xml and jOpenDocument
希望保留java.xml中的org.w3c.dom包,排除jOpenDocument中的该包(仅包含org.w3c.dom.UserDataHandler.class,移除后副作用小)。尝试了如下build.gradle配置但无效,因为org.w3c.dom是Java包而非Gradle/Maven模块:
dependencies { testImplementation 'org.testng:testng:7.4.0' implementation 'org.apache.logging.log4j:log4j-api:2.14.1' implementation 'org.apache.logging.log4j:log4j-core:2.14.1' implementation ('libs:jOpenDocument-1.5') { exclude module: 'org.w3c.dom' } }
咨询两个问题:
- 应如何修改build.gradle文件以解决该重复依赖冲突?
- 若Gradle构建依赖模块不是Java包,那它指的是什么?
解决方案
1. 解决重复包冲突的配置方式
Gradle的exclude机制只能排除整个依赖模块,无法直接移除jar包内的单个类或包。要解决这个问题,需要先处理jOpenDocument的jar包,移除冲突的org.w3c.dom.UserDataHandler.class,再依赖处理后的jar包。可以通过自定义Gradle任务实现:
// 自定义任务:处理jOpenDocument原jar,移除冲突类 task processJOpenDocumentJar(type: Jar) { // 读取原jar文件 from zipTree(file('libs/jOpenDocument-1.5.jar')) // 排除冲突的类文件 exclude 'org/w3c/dom/UserDataHandler.class' // 设置处理后的jar文件名 archiveFileName = 'jOpenDocument-processed-1.5.jar' // 指定处理后的jar输出目录 destinationDirectory = file("$buildDir/libs") } dependencies { testImplementation 'org.testng:testng:7.4.0' implementation 'org.apache.logging.log4j:log4j-api:2.14.1' implementation 'org.apache.logging.log4j:log4j-core:2.14.1' // 依赖处理后的jar包,指定该jar由processJOpenDocumentJar任务生成 implementation files("$buildDir/libs/jOpenDocument-processed-1.5.jar") { builtBy processJOpenDocumentJar } }
执行构建时,Gradle会先运行processJOpenDocumentJar任务生成处理后的jar,再用这个jar参与构建,避免包重复读取的问题。
2. Gradle依赖模块的定义
Gradle中的依赖模块不是Java包(package),而是Maven/Gradle生态中的独立依赖单元:
- 通常对应一个可执行的jar/war/aar等文件,每个模块有唯一的
group:name:version标识(例如org.apache.logging.log4j:log4j-core:2.14.1)。 - 一个模块可以包含多个Java包,同时一个Java包也可能被多个模块包含(比如本次问题中的
org.w3c.dom被JDK的java.xml模块和jOpenDocument模块同时包含)。 - Gradle的
exclude机制作用于整个模块或模块的子依赖,无法直接操作单个Java包或类。
内容的提问来源于stack exchange,提问作者Emma Atkinson
相关产品推荐
相关产品推荐

