使用Jacoco+Gradle生成覆盖率报告报错:无法添加同名不同类
问题:Jacoco生成集成测试覆盖率报告时出现同名类冲突错误
尝试用Jacoco插件和Gradle生成集成测试覆盖率报告时,抛出以下错误:
java.lang.IllegalStateException: Can't add different class with same name: com/example/application/Application at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:106) at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:99) at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:377) at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:100) at org.objectweb.asm.ClassReader.accept(ClassReader.java:725) at org.objectweb.asm.ClassReader.accept(ClassReader.java:401) at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:116) at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:132) Caused: java.io.IOException: Error while analyzing C:\Users\p-bri\.jenkins\jobs\ProjectAssignmentOne-ParallelBuildDeclarative\builds\5\jacoco\classes\java\main\com\example\application\Application.class. at org.jacoco.core.analysis.Analyzer.analyzerError(Analyzer.java:162) at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:134) at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:157) at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:193) at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:226) at hudson.plugins.jacoco.ExecutionFileLoader.analyzeStructure(ExecutionFileLoader.java:127) Caused: java.io.IOException: While reading class directory: C:\Users\p-bri\.jenkins\jobs\ProjectAssignmentOne-ParallelBuildDeclarative\builds\5\jacoco\classes at hudson.plugins.jacoco.ExecutionFileLoader.analyzeStructure(ExecutionFileLoader.java:130) at hudson.plugins.jacoco.ExecutionFileLoader.loadBundleCoverage(ExecutionFileLoader.java:138) at hudson.plugins.jacoco.JacocoReportDir.parse(JacocoReportDir.java:110) at hudson.plugins.jacoco.JacocoBuildAction.loadRatios(JacocoBuildAction.java:331) at hudson.plugins.jacoco.JacocoBuildAction.load(JacocoBuildAction.java:321) at hudson.plugins.jacoco.JacocoPublisher.perform(JacocoPublisher.java:675) at jenkins.tasks.SimpleBuildStep.perform(SimpleBuildStep.java:123) at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:100) at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:70) at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)
Jenkins声明式流水线中生成报告的阶段配置:
stage('Integration Test Coverage report') { steps { dir('') { jacoco exclusionPattern: '**/*Test*.class,**/groovy/**', classPattern: '**/classes', sourcePattern: '**/src/main/java', execPattern: '**/integrationTest.exec' } } }
Jenkins日志中的匹配信息:
[JaCoCo plugin] Number of found exec files for pattern **/integrationTest.exec: 1 [JaCoCo plugin] Saving matched execfiles: C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\build\jacoco\integrationTest.exec [JaCoCo plugin] Saving matched class directories for class-pattern: **/classes: [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\artifacts\parallel_build\reports\tests\integrationTest\classes 0 files [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\artifacts\sequential_build\reports\tests\integrationTest\classes 0 files [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\build\classes 24 files [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\build\reports\tests\integrationTest\classes 0 files [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\node_modules\semver\classes 0 files [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\war\WEB-INF\classes 22 files [JaCoCo plugin] Saving matched source directories for source-pattern: **/src/main/java: [JaCoCo plugin] Source Inclusions: **/*.java,**/*.groovy,**/*.kt,**/*.kts [JaCoCo plugin] Source Exclusions: [JaCoCo plugin] - C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\src\main\java 17 files [JaCoCo plugin] Loading inclusions files.. [JaCoCo plugin] inclusions: [] [JaCoCo plugin] exclusions: [**/*Test*.class, **/groovy/**]
根据Jacoco FAQ,该错误源于存在同名但不同的类,但日志未明确指出具体冲突位置,请问如何定位并解决?
定位与解决方法
一、定位冲突类
- 从报错信息明确冲突类为
com/example/application/Application,结合Jenkins日志,Jacoco扫描了两个含有效类文件的目录:build/classes和war/WEB-INF/classes。直接在这两个目录下查找该类文件:- 进入
C:\Users\p-bri\.jenkins\workspace\ProjectAssignmentOne-ParallelBuildDeclarative\build\classes,搜索com/example/application/Application.class - 进入
war/WEB-INF/classes目录,同样搜索该类文件
- 进入
- 对比两个文件差异:使用
javap -v命令查看字节码详情,比如分别执行javap -v build/classes/com/example/application/Application.class和javap -v war/WEB-INF/classes/com/example/application/Application.class,通过版本、方法表、常量池等信息确认是否为重复编译或打包导致的重复类。
二、解决方法
1. 精确配置Jacoco的classPattern
当前classPattern: '**/classes'会扫描所有含classes的目录,包括war包解压后的重复类目录。将其修改为指向Gradle编译生成的主类目录,避免重复扫描:
jacoco exclusionPattern: '**/*Test*.class,**/groovy/**', classPattern: 'build/classes/java/main', sourcePattern: 'src/main/java', execPattern: 'build/jacoco/integrationTest.exec'
2. 清理冗余classes目录
检查项目构建流程,确认war/WEB-INF/classes是否为多余生成目录。如果是打包时自动复制的产物,可在生成Jacoco报告前手动清理该目录,或在Gradle构建脚本中调整打包逻辑,避免重复生成。
3. 排除war目录下的classes
若必须保留war目录,可在exclusionPattern中添加war下的classes路径,排除重复扫描:
jacoco exclusionPattern: '**/*Test*.class,**/groovy/**,**/war/WEB-INF/classes/**', classPattern: '**/classes', sourcePattern: '**/src/main/java', execPattern: '**/integrationTest.exec'
内容的提问来源于stack exchange,提问作者Fábio Pires
相关产品推荐
相关产品推荐

