Java jacoco 代码覆盖率报告生成器显示错误:“包‘代码覆盖率报告’中的类与执行数据不匹配”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31720139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jacoco code coverage report generator showing error : "Classes in bundle 'Code Coverage Report' do no match with execution data"
提问by Nishant Lakhara
I am generating jacoco report by using jacoco:report tag. I am getting errors like :
我正在使用 jacoco:report 标签生成 jacoco 报告。我收到如下错误:
[jacoco:report] Classes in bundle 'Code Coverage Report' do no match with execution data. For report generation the same class files must be used as at runtime.
[jacoco:report] Execution data for class xxxxx does not match.
[jacoco:report] Execution data for class yyyyy does not match.
The ant report target looks like :
蚂蚁报告目标看起来像:
<target name="report">
<jacoco:report>
<executiondata>
<file file="${jacocoexec.dir}/${jacocoexec.filename}"/>
</executiondata>
<!-- the class files and optional source files ... -->
<structure name="Code Coverage Report">
<classfiles>
<fileset file="./jar/abc.jar"/>
</classfiles>
<sourcefiles>
<fileset dir="./code/src"/>
</sourcefiles>
</structure>
<!-- to produce reports in different formats. -->
<html destdir="${jacoco.report.dir}"/>
</jacoco:report>
</target>
The abc.jar
so generated is by using ./code/src
only. Then why is it giving such errors. Any idea?
的abc.jar
产生所以是通过使用./code/src
仅。那为什么会出现这样的错误。任何的想法?
回答by kkmonlee
JaCoCo needs the exact same class files for report generation that used at execution time. Due to different compilers and/or other tools modifying the classes, the classes might be different.
JaCoCo 需要与执行时使用的报告生成完全相同的类文件。由于不同的编译器和/或其他修改类的工具,类可能会有所不同。
回答by Jayan
You are getting the error related to classID. This is a concept described in detail at JaCoCo docs-site. http://www.eclemma.org/jacoco/trunk/doc/classids.html. This is a key step for supporting multiple versions of class (an appserver for example) in same JVM.
您收到与 classID 相关的错误。这是在 JaCoCo docs-site 上详细描述的概念。http://www.eclemma.org/jacoco/trunk/doc/classids.html。这是在同一 JVM 中支持多个版本的类(例如应用程序服务器)的关键步骤。
Copying part some part of it here for visibility.
在这里复制部分内容以供查看。
What are class ids and how are they created?
什么是类 ID,它们是如何创建的?
Class ids are 64-bit integer values, for example 0x638e104737889183 in hex notation. Their calculation is considered an implementation detail of JaCoCo. Currently ids are created with a CRC64 checksum of the raw class file.
类 ID 是 64 位整数值,例如 0x638e104737889183 以十六进制表示法。他们的计算被认为是 JaCoCo 的一个实现细节。目前 id 是使用原始类文件的 CRC64 校验和创建的。
What can cause different class ids?
什么会导致不同的类 ID?
Class ids are identical for the exact same class file only (byte-by-byte). There is a couple of reasons why you might get different class files. First compiling Java source files will result in different class files if you use a different tool chain:
仅对于完全相同的类文件(逐字节),类 ID 是相同的。您可能会获得不同的类文件有几个原因。如果使用不同的工具链,首先编译 Java 源文件将产生不同的类文件:
Different compiler vendor (e.g. Eclipse vs. Oracle JDK)
Different compiler versions
Different compiler settings (e.g. debug vs. non-debug)
不同的编译器供应商(例如 Eclipse 与 Oracle JDK)
不同的编译器版本
不同的编译器设置(例如调试与非调试)
Also post-processing class files (obfuscation, AspectJ, etc.) will typically change the class files. JaCoCo will work well if you simply use the same class files for runtime as well as for analysis. So the tool chain to create these class files does not matter.
此外,后处理类文件(混淆、AspectJ 等)通常会更改类文件。如果您只是将相同的类文件用于运行时和分析,那么 JaCoCo 将运行良好。所以创建这些类文件的工具链并不重要。
Even if the class files on the file system are the same there is possible that classes seen by the JaCoCo runtime agent are different anyways. This typically happens when another Java agent is configured before the JaCoCo agent or special class loaders pre-process the class files. Typical candidates are:
即使文件系统上的类文件相同,JaCoCo 运行时代理看到的类也可能不同。这通常发生在在 JaCoCo 代理或特殊类加载器预处理类文件之前配置另一个 Java 代理时。典型的候选人是:
- Mocking frameworks
- Application servers
- Persistence frameworks
- 模拟框架
- 应用服务器
- 持久性框架
The same page covers possible solutions.
同一页涵盖了可能的解决方案。
What workarounds exist to deal with runtime-modified classes?
有哪些解决方法可以处理运行时修改的类?
If classes get modified at runtime in your setup there are some workarounds to make JaCoCo work anyways:
如果在您的设置中的运行时类被修改,则有一些解决方法可以使 JaCoCo 无论如何工作:
- If you use another Java agent make sure the JaCoCo agent is specified at first in the command line. This way the JaCoCo agent should see the original class files.
- Specify the classdumpdir option of the JaCoCo agent and use the dumped classes at report generation. Note that only loaded classes will be dumped, i.e. classes not executed at all will not show-up in your report as not covered.
- Use offline instrumentation before you run your tests. This way classes get instrumented by JaCoCo before any runtime modification can take place. Note that in this case the report has to be generated with the original classes, not with instrumented ones.
- 如果您使用其他 Java 代理,请确保首先在命令行中指定 JaCoCo 代理。这样 JaCoCo 代理应该看到原始类文件。
- 指定 JaCoCo 代理的 classdumpdir 选项并在报告生成时使用转储的类。请注意,只会转储已加载的类,即根本未执行的类将不会显示在您的报告中,因为未涵盖。
- 在运行测试之前使用离线检测。通过这种方式,JaCoCo 可以在任何运行时修改发生之前检测类。请注意,在这种情况下,报告必须使用原始类生成,而不是使用检测类生成。
Edited on 22-02-2017
编辑于 22-02-2017
How to use Offline Instrumentation:Use below task provided by Daniel Atallah.
如何使用离线仪器:使用Daniel Atallah提供的以下任务。
//Additional SourceSets can be added to the jacocoOfflineSourceSets as needed by
project.ext.jacocoOfflineSourceSets = [ 'main' ]
task doJacocoOfflineInstrumentation(dependsOn: [ classes, project.configurations.jacocoAnt ]) {
inputs.files classes.outputs.files
File outputDir = new File(project.buildDir, 'instrumentedClasses')
outputs.dir outputDir
doFirst {
project.delete(outputDir)
ant.taskdef(
resource: 'org/jacoco/ant/antlib.xml',
classpath: project.configurations.jacocoAnt.asPath,
uri: 'jacoco'
)
def instrumented = false
jacocoOfflineSourceSets.each { sourceSetName ->
if (file(sourceSets[sourceSetName].output.classesDir).exists()) {
def instrumentedClassedDir = "${outputDir}/${sourceSetName}"
ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
fileset(dir: sourceSets[sourceSetName].output.classesDir, includes: '**/*.class')
}
//Replace the classes dir in the test classpath with the instrumented one
sourceSets.test.runtimeClasspath -= files(sourceSets[sourceSetName].output.classesDir)
sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
instrumented = true
}
}
if (instrumented) {
//Disable class verification based on https://github.com/jayway/powermock/issues/375
test.jvmArgs += '-noverify'
}
}
}
test.dependsOn doJacocoOfflineInstrumentation
Now generate report using "gradlew test jacocoTestReport"
command.
现在使用"gradlew test jacocoTestReport"
命令生成报告。