【问题标题】:Testng, Emma, Cobertura, coverage and JDK 7 result in ClassFormatError and VerifyErrorTestng、Emma、Cobertura、coverage 和 JDK 7 导致 ClassFormatError 和 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

标签: code-coverage java-7 cobertura emma jacoco


【解决方案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 之前,您必须遵循以下步骤:stackoverflow.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 语法。
      • 这似乎不是真的。我遇到了同样的问题,但我没有进行任何源更改。
      猜你喜欢
      • 1970-01-01
      • 2011-05-25
      • 2013-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-02
      • 2018-01-22
      相关资源
      最近更新 更多