看起来这是与 Sonar 的 JaCoCo 代码覆盖率组件相关的问题。JaCoCo 处理编译后的字节码而不是 Java 源代码,Java 编译器可以生成与底层源代码不直接相关的代码。
查看JaCoCo的文档,有一段内容如下(强调添加):
在某些情况下,为什么特定线条具有突出显示或具有特定颜色并不明显。原因是底层代码覆盖库 JaCoCo 仅适用于 Java 类文件。在某些情况下,Java 编译器会为特定的源代码行创建额外的字节码。这种情况可能会被 JaCoCo/EclEmma 的未来版本过滤掉。
按照文章中的链接,您将转到 Jacoco 的 GH 站点上的FilteringOptions页面,其中提到了 JDK 可能生成代码的多种方式,这些代码将触发这些“虚假”代码覆盖警告。
然而,这不是这里的作用(或不完全是)。
如前所述,JaCoCo 在 Java 字节码上工作,因此编译器生成的任何不直接归因于源代码的代码都将计入覆盖范围。
在我的具体情况下,我有一个assert
which 在源代码中代表断言发生点的分支,但也代表“全局”级别。如果您查看Foo
上面定义的类的字节码(执行 a javap -c Foo
),您会看到:
Compiled from "Foo.java"
public class Foo extends java.lang.Object{
static final boolean $assertionsDisabled;
Foo(java.lang.String);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: getstatic #2; //Field $assertionsDisabled:Z
7: ifne 22
10: aload_1
11: ifnonnull 22
14: new #3; //class java/lang/AssertionError
17: dup
18: invokespecial #4; //Method java/lang/AssertionError."<init>":()V
21: athrow
22: return
static {};
Code:
0: ldc_w #5; //class Foo
3: invokevirtual #6; //Method java/lang/Class.desiredAssertionStatus:()Z
6: ifne 13
9: iconst_1
10: goto 14
13: iconst_0
14: putstatic #2; //Field $assertionsDisabled:Z
17: return
请注意第 7 行,这是一个条件分支,取决于是否启用了断言。因此,如果您有一个包含纯 Java 的类assert
,您将在字节码中的某处有这个分支,这就是在类声明中产生“执行 N/2 个分支”覆盖警告的原因,其中 N 为 0 或1 取决于该课程是否曾通过测试 (1) 或未 (0) 进行过测试。
编辑:请注意, https : //sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions 中也提到了这一点:
抛出 AssertionErrors 的块 - 如果出现条件(如果 !assertion throw new AssertionError),则应忽略整个块