Gradle中使用ANTLR4时遭遇ow2.asm依赖冲突导致任务执行失败
看起来你遇到的是Gradle自带ASM版本与手动引入的ASM 9.6版本不兼容的问题,核心原因是两个版本的ASM类结构存在差异,导致Gradle的worker进程在类转换时出现类型匹配错误(ClassRemapper无法转换为ClassVisitor)。下面给你几个可行的解决方案,你可以根据自身需求选择:
方案一:排除ANTLR4依赖中的ASM,复用Gradle自带版本
ANTLR4本身依赖ASM,但你可以让它复用Gradle内置的兼容版本(和你的Gradle 7.6.4适配),同时保留自己的ASM依赖。修改dependencies块如下:
dependencies { antlr4('org.antlr:antlr4:4.13.2') { // 排除ANTLR4自带的所有ASM相关依赖 exclude group: 'org.ow2.asm', module: 'asm' exclude group: 'org.ow2.asm', module: 'asm-commons' exclude group: 'org.ow2.asm', module: 'asm-tree' exclude group: 'org.ow2.asm', module: 'asm-analysis' exclude group: 'org.ow2.asm', module: 'asm-util' } // 保留你的ASM依赖,如果代码仅编译时需要ASM,建议改为compileOnly以避免进入runtime类路径 implementation('org.ow2.asm:asm:9.6') // 若仅编译时用,替换为:compileOnly 'org.ow2.asm:asm:9.6' }
这样ANTLR4会使用Gradle内置的兼容ASM版本,你的代码依然可以使用自己引入的ASM 9.6,同时不会污染Gradle worker进程的类路径。
方案二:强制所有依赖使用与Gradle兼容的ASM版本
如果你的代码可以兼容Gradle 7.6.4自带的ASM版本(通常是9.3),可以强制所有依赖统一使用这个版本,从根源消除版本差异:
configurations.all { resolutionStrategy.force 'org.ow2.asm:asm:9.3' resolutionStrategy.force 'org.ow2.asm:asm-commons:9.3' resolutionStrategy.force 'org.ow2.asm:asm-tree:9.3' } dependencies { antlr4 group: 'org.antlr', name: 'antlr4', version: '4.13.2' implementation group: 'org.ow2.asm', name: 'asm', version: '9.6' // 此处版本会被强制替换为9.3 }
这个方法操作最简单,但前提是你的代码不需要ASM 9.6的独有特性。
方案三:严格隔离ANTLR任务的类路径
如果必须保留ASM 9.6且不能修改依赖版本,可以让ANTLR任务的worker进程仅加载ANTLR4的依赖,完全排除你的ASM依赖。修改generateGrammar任务:
task generateGrammar(type: AntlrTask) { source = files("./src/grammar.g4") // 仅使用ANTLR4的类路径,过滤掉所有外部ASM依赖 antlrClasspath = configurations.antlr4.filter { !it.group.startsWith('org.ow2.asm') } outputDirectory = file("./src/antlr4") doFirst { outputDirectory.mkdirs() // 强制任务类路径仅包含ANTLR4和Gradle核心依赖 classpath = configurations.antlr4 + gradle.gradleHomeDir.listFiles().findAll { it.name.startsWith('gradle-') }.collect { file("${it.path}/lib") }.flatten() } }
这个方法通过严格限制任务的类加载范围,避免冲突的ASM版本被Gradle worker进程加载。
问题根源补充
Gradle的worker进程会使用独立的类加载器处理任务执行,当你引入的ASM版本与Gradle内置版本不一致时,会出现类结构不兼容——比如在某个ASM版本中,ClassRemapper的继承关系发生了变化,不再直接继承ClassVisitor,最终触发类型转换错误。你移除ASM依赖后任务恢复正常,也直接验证了这是版本冲突导致的问题。
内容来源于stack exchange

