Testng、Emma、Cobertura、coverage 和 JDK 7 导致 ClassFormatError 和 VerifyError
Posted
技术标签:
【中文标题】Testng、Emma、Cobertura、coverage 和 JDK 7 导致 ClassFormatError 和 VerifyError【英文标题】:Testng, Emma, Cobertura, coverage and JDK 7 result in ClassFormatError and VerifyError 【发布时间】:2011-10-24 01:13:19 【问题描述】:我已切换到最新的 JDK 7,但在对 emma 覆盖工具处理的字节码运行 testng 单元测试时遇到问题。我的所有测试用例都没有正确运行,而且大多数测试用例都收到了此类错误。
java.lang.ClassFormatError: Illegal local variable table length 10 in method measurement.meter.AbstractSerialPortMeter.<init>(Lmeasurement/meter/SerialPort;)V at measurement.meter.Elc3133aTest.setUp(Elc3133aTest.java:42)
我在这里找到了一篇文章JSR 292 Goodness Fast Code Coverage Tool Less 10k, 这就是说“JSR 292 引入了一个新的字节码指令invokedynamic,但也引入了几种新的常量池常量。这意味着大多数解析字节码的工具,如 ASM、BCEL、findbugs 或 EMMA 都需要更新为 java 7兼容。”
查看了Emma主页,但是好像很久没更新了。
有人解决过类似的问题吗?
我也尝试过使用 Cobertura。它看起来工作得更好一些,但我收到了很多 VerifyError
类型的异常。
java.lang.VerifyError: Expecting a stackmap frame at branch target 85 in method measurement.meter.AbstractSerialPortMeter.close()V at offset 26
at measurement.meter.AbstractSerialPortMeterTest.setUp(AbstractSerialPortMeterTest.java:27)
【问题讨论】:
我认为没有人会在短期内迁移到 Java7,因为目前还不知道它有多少错误和安全漏洞,所以我建议你也这样做。同时,正如您所提到的,EMMA 已经很久没有更新了,足以认为它几乎是一个死项目。我建议您在几个月后尝试 Cobertura,因为它在 Java7 上也存在一些问题,但与 EMMA 不同,正在进行的开发很少(最后一次更改是 2 个月前) 感谢您的提示。我会尝试 Cobertura。回到 JDK 6 不是一个选项,因为我的目标正是检查 JDK 7 的性能。 :-) 我在 Java7 项目的 Eclipse 3.7.1 中运行 EMMA 时遇到了完全相同的问题。 是的,我写这个问题已经有一段时间了,但 Cobertura 和 Emma 仍然没有得到更新。这有点令人沮丧,但好吧,我猜我们对此无能为力。 不确定 cobertura,但 eclemma 家伙似乎已经创建了自己的 Java 7 兼容覆盖引擎,称为 JaCoCo eclemma.org/jacoco/trunk/index.html 【参考方案1】:Pedro Ballesteros 的答案相当于 Java 8+:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<argLine>-noverify</argLine>
</configuration>
</plugin>
(调整版本号以匹配您使用的 Surefire 版本。)
【讨论】:
【参考方案2】:我在使用 maven cobertura 插件时遇到了同样的问题。从 cobertura:report 运行时,所有测试均失败。但是当直接从surefire插件运行时,所有测试都成功了。正如你们中的一些人已经说过的那样,问题是 coberture 字节码检测与 JDK7 不兼容。
您可以在这里看到http://vikashazrati.wordpress.com/2011/10/09/quicktip-verifyerror-with-jdk-7/,该异常与“具有 StackMapTable 属性的新类型检查器”有关(请参阅:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html 中的 -X:+UseSplitVerifier JVM 选项)。
所以我的解决方案是配置 Surefire-plugin 以始终使用 JVM arg "-XX:-UseSplitVerifier 执行测试。无论有没有 cobertura 仪器,它都可以正常工作。
我在 maven 中的万无一失的配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<argLine>-XX:-UseSplitVerifier</argLine>
</configuration>
</plugin>
【讨论】:
将此添加到 Eclipse“Coverage Configurations...”中的“VM Arguments”。效果很好。 Tks 佩德罗;非常适合我。同样的配置,同样的问题。相同的解决方案。 @dkantowitz 你是天才!它在 Eclipse 中完美运行。如果您可以在 Eclipse 的代码编辑器中看到所有结果,为什么还要一直使用 Surefire?您应该将您的帖子作为***帖子,因为它真的非常有帮助。另外值得一提的是,在 Kepler 中使用 Cobertura 之前,您必须遵循以下步骤:***.com/questions/18630141/… @nucleo 感谢您的客气话。我很高兴我的笔记对你有所帮助。老实说,我什至不记得写评论或当时我在做什么。整个事情可能是一个人处理并迅速忘记的那些通过它/修复愚蠢的Java垃圾的事情之一;在当时看来,只值一个简短的评论。 @Pedro Ballesteros 使用上述配置,它上周解决了我的问题。但今天又出现了。【参考方案3】:我让 Gradle 1.0M9、Java 7 和 EMMA 2.1 与此处建议的补丁一起工作:使用 jvm 参数。
这里有详细信息... http://marcellodesales.wordpress.com/2012/04/03/running-emma-code-test-coverage-with-java-7-and-gradle-1-0m9/?preview=true&preview_id=179&preview_nonce=261e892908
configurations
emma
dependencies
// EMMS Code Coverage
emma "emma:emma:2.1.5320"
emma "emma:emma_ant:2.1.5320"
...
testCompile group: 'junit', name: 'junit', version: '4.9'
test
// add EMMA related JVM args to our tests
jvmArgs "-XX:-UseSplitVerifier", "-Demma.coverage.out.file=$buildDir/tmp/emma/metadata.emma", "-Demma.coverage.out.merge=true"
doFirst
println "Instrumenting the classes at " + sourceSets.main.output.classesDir.absolutePath
// define the custom EMMA ant tasks
ant.taskdef( resource:"emma_ant.properties", classpath: configurations.emma.asPath)
ant.path(id:"run.classpath")
pathelement(location:sourceSets.main.output.classesDir.absolutePath)
def emmaInstDir = new File(sourceSets.main.output.classesDir.parentFile.parentFile, "tmp/emma/instr")
emmaInstDir.mkdirs()
println "Creating $emmaInstDir to instrument from " + sourceSets.main.output.classesDir.absolutePath
// instruct our compiled classes and store them at $buildDir/tmp/emma/instr
ant.emma(enabled: 'true', verbosity:'info')
instr(merge:"true", destdir: emmaInstDir.absolutePath, instrpathref:"run.classpath",
metadatafile: new File(emmaInstDir, '/metadata.emma').absolutePath)
instrpath
fileset(dir:sourceSets.main.output.classesDir.absolutePath, includes:"**/*.class")
setClasspath(files("$buildDir/tmp/emma/instr") + configurations.emma + getClasspath())
// The report should be generated directly after the tests are done.
// We create three types (txt, html, xml) of reports here. Running your build script now should
// result in output like that:
doLast
def srcDir = sourceSets.main.java.srcDirs.toArray()[0]
println "Creating test coverage reports for classes " + srcDir
def emmaInstDir = new File(sourceSets.main.output.classesDir.parentFile.parentFile, "tmp/emma")
ant.emma(enabled:"true")
new File("$buildDir/reports/emma").mkdirs()
report(sourcepath: srcDir)
fileset(dir: emmaInstDir.absolutePath)
include(name:"**/*.emma")
txt(outfile:"$buildDir/reports/emma/coverage.txt")
html(outfile:"$buildDir/reports/emma/coverage.html")
xml(outfile:"$buildDir/reports/emma/coverage.xml")
println "Test coverage reports available at $buildDir/reports/emma."
println "txt: $buildDir/reports/emma/coverage.txt"
println "Test $buildDir/reports/emma/coverage.html"
println "Test $buildDir/reports/emma/coverage.xml"
运行“gradle test”会得到以下结果:
marcello@hawaii:/u1/development/workspaces/open-source/interviews/vmware$ gradle test
:compileJava
:processResources UP-TO-DATE
:classes
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
Instrumenting the classes at /u1/development/workspaces/open-source/interviews/vmware/build/classes/main
Creating /u1/development/workspaces/open-source/interviews/vmware/build/tmp/emma/instr to instrument from /u1/development/workspaces/open-source/interviews/vmware/build/classes/main
Creating test coverage reports for classes /u1/development/workspaces/open-source/interviews/vmware/src/main/java
Test coverage reports available at /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma.
txt: /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma/coverage.txt
Test /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma/coverage.html
Test /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma/coverage.xml
BUILD SUCCESSFUL
【讨论】:
jvmArgs "-XX:-UseSplitVerifier" 为我做了。谢谢!【参考方案4】:IntelliJ IDEA 11 的内部覆盖工具适用于我的项目,使用 try-with-resources、菱形运算符,但我们没有使用 invokedynamic。我认为社区版中不包含覆盖工具,只有终极版。
我还没有尝试过 jacoco - 大部分 emma 的前开发人员似乎都去了那里。
【讨论】:
JaCoCo 看起来很完美,与其他工具相比,它不使用字节码检测(Emma、Cobertura)或源代码检测(Clover)等检测。我不知道细节,但看起来它重用了调试信息并作为 Java 代理工作,这简化了构建过程中的许多任务。 事实上,JaCoCo 执行字节码检测,但与 Emma 和 Cobertura 相比 - 即时。【参考方案5】:我遇到了这个问题。使用 Eclipse 市场升级到 2.0.1.201112281951 对我有用。
【讨论】:
【参考方案6】:我有同样的问题。 幸运的是,测试版适用于 JDK 7。 更新网址:http://download.eclipselab.org/eclemma/beta/2.0.0/update/ 此链接应在 Eclipse 中使用:
Help -> Install new software... -> Add...
休息应该很容易;)
【讨论】:
点击您提供的链接后,我得到了 xml 响应 Access Denied。但是,通过链接的内容,我可以看出这是一个 emma Eclipse 插件。您是否也将其作为 Ant 任务运行? Ant 任务是我最需要的。 好的,已经想通了。我应该在 Eclipse“安装新软件...”中使用它 你给我的提示,把我带到了 JaCoCo:eclemma.org/jacoco/trunk/index.html,它对我来说完美无缺,满足了我的所有要求。因此我接受这个答案。【参考方案7】:如果您不使用新的语言功能(例如 try-with-resources 等),Emma 就可以工作。您可以通过新库(Paths、DirectoryStream 等)使用 Java 7。 我知道这不能解决您的问题,但如果您只想检查“JDK 7 的执行情况”,它可能会起作用...
【讨论】:
切换到 Java 7 后,我对旧代码进行了重构,因此确实不能返回,但感谢您的提示。由于我的代码符合最新版本的 Java,我无法检查它是否仍然适用于 Java 6 语法。 这似乎不是真的。我遇到了同样的问题,但我没有进行任何源更改。以上是关于Testng、Emma、Cobertura、coverage 和 JDK 7 导致 ClassFormatError 和 VerifyError的主要内容,如果未能解决你的问题,请参考以下文章
是否有将 Emma XML 报告转换为 Cobertura XML 格式的工具?
当 cobertura 测试在 maven-cobertura-plugin 中运行时如何配置?
使用 maven 运行 junits 和 cobertura