DEBUG.WIKI
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

Gradle 9.7.0 的 Ant taskdef 加载错 Groovy,showInternal 属性为何不支持

Gradle 9.7.0 的父加载器暴露内部 Groovy,覆盖 taskdef 指定的实现。检查类来源,采用包含修复的 9.7.1 并保留任务依赖。

升级到 Gradle 9.7.0 后,自定义 Groovydoc 任务报 groovydoc doesn't support the "showInternal" attribute,而 ant.taskdef 明明传了新 Groovy 的 classpath。先检查任务类实际从哪个 JAR 加载:这个版本可能优先拿到 Gradle 发行包自带的 Groovy,而不是构建提供的那一份。

这是类加载可见性回归。Gradle 9.7.1 已列入修复;没有必要为了消掉报错,先删掉文档任务需要的属性。

声明的 classpath 与实际来源不一致

在受影响构建中,项目提供的 org.codehaus.groovy.ant.Groovydoc 支持新属性,Gradle 9.7.0 内置的 groovy-ant-4.0.32.jar 不支持。父级应用类加载器暴露了发行包内部 JAR,同名类先被它解析,显式任务 classpath 没有选中预期实现。

同一任务在 9.6.1 下会使用所提供的任务类路径。9.7.0 即使拿到不含该类的 classpath,也可能意外从发行包内部找到它。这种“成功找到类”反而遮住了依赖问题;直到新旧任务属性不同时才显现。

可在原 taskdef 注册后查看类来源。下面是 Groovy DSL 的独立诊断任务,taskdefCp 需由你传入实际 Ant 任务及其完整依赖路径,不能只照抄一个不存在的 JAR:

tasks.register('probeAntClass') {
    doLast {
        def cp = System.getProperty('taskdefCp')
        if (!cp) {
            throw new GradleException('Supply -DtaskdefCp with the task classpath')
        }
        ant.taskdef(name: 'gd',
                classname: 'org.codehaus.groovy.ant.Groovydoc',
                classpath: cp)
        Class<?> cls = ant.project.taskDefinitions['gd']
        println "class from: ${cls.protectionDomain.codeSource?.location}"
        println "loader: ${cls.classLoader}"
    }
}

从项目 Wrapper 执行该任务,并按操作系统的路径分隔规则传入类路径。输出若指向 gradle-9.7.0/lib/groovy-ant-4.0.32.jar,而非你提供的任务实现,就符合本题。若来源已经正确,应继续核对该 JAR 真实支持的属性,不能把所有 Ant 属性错误都归为 Gradle 回归。

采用包含修复的发行版本,保留任务依赖

优先选择项目插件与运行 JDK 兼容、且包含此项修复的正式版本;9.7.1 是已经明确列入修复的版本。按项目原有 Wrapper 更新流程维护脚本、JAR、属性及发行包校验,保留修改前版本,以便恢复整个构建组合。

修复恢复了精简的应用类加载路径,避免把 Gradle 整套内部运行依赖泄露到 Ant 任务的父加载器。它不会替你补齐自定义任务 classpath:升级后若出现真正的 ClassNotFoundException,要检查任务依赖是否完整,不能再依赖 Gradle 内置 JAR 偶然兜底。

不要把新 Groovy JAR 复制到 Gradle 安装目录,也不要全局强制替换 Gradle 自身使用的 Groovy。自定义 Ant 任务和构建脚本运行时承担不同职责,这些做法会把局部任务问题扩散到整个构建。清空所有 Gradle 缓存也不会改变父加载器中已选中的类。

暂时无法升级时,可在兼容性允许的条件下恢复项目此前可用的完整 Wrapper 基线,而不是只降一个 Ant 依赖。对本题已比较的基线是 9.6.1;是否适合你的插件和 JDK,仍需按项目约束决定。

完成后再次确认类来源,再运行原来失败的 Groovydoc 任务,检查 showInternal 等需要的属性确实生效、文档内容符合预期。只看到诊断任务加载成功,或者简单删除属性后构建变绿,都没有验证原有文档要求。