Android端代码染色原理及技术实践

导读

高德地图开放平台产品不断迭代,代码逻辑越来越复杂,现有的测试流程不能保证完全覆盖所有业务代码,测试不到的代码及分支,会存在一定的风险。为了保证测试全面覆盖,需要引入代码覆盖率做为测试指标,需要对SDK代码进行染色,测试结束后可生成代码覆盖率报告,作为发版前的一项重要卡点指标。本文小结了Android端代码染色原理及技术实践。

JaCoCo工具

JaCoCo有以下优点:

  • 支持Ant和Gradle打包方式,可以自由切换。

  • 支持离线模式,更贴合SDK的使用场景。

  • JaCoCo文档比较全面,还在持续维护,有问题便于解决。

JaCoCo主要是通过ASM技术对Java字节码进行处理和插桩,ASM和Java字节码技术不是本文重点,感兴趣的朋友可以自行了解。下面重点介绍JaCoCo的插桩原理。

 

Jacoco探针

由于Java字节码是线性的指令序列,所以JaCoCo主要是利用ASM处理字节码,在需要的地方插入一些特殊代码。

我们通过Test1方法观察一下JaCoCo做的处理。

//原始java方法
  public static int Test1(int a, int b) {
        int c = a + b;
        int d = c + a;
        return d;
   }
//--------------------------我是分割线--------------------------------------------//
//jacoco处理后的方法
    private static transient /* synthetic */ boolean[] $jacocoData;


    public static int Test1(final int a, final int b) {
        final boolean[] $jacocoInit = $jacocoInit();
        final int c = a + b;
        final int n;
        final int d = n = c + a;
        $jacocoInit[3] = true;
        return n;
}
  private static  boolean[] $jacocoInit() {
        boolean[] $jacocoData;
      if (($jacocoData = TestInstrument.$jacocoData) == null) {
            $jacocoData = (TestInstrument.$jacocoData = 
                           Offline.getProbes(-6846167369868599525L,
                                             "com/jacoco/test/TestInstrument", 4));
        }
        return $jacocoData;
}

可以看出代码中插入了多个Boolean数组赋值,自动添加了jacocoInit方法和jacocoData数组声明。

JaCoCo统计覆盖率就是标记Boolean数组, 只要执行过的代码,就对相应角标的Boolean数组进行赋值, 最后对Boolean进行统计即可得出覆盖率,这个数组官方的名字叫探针 (Probe)。

探针是由以下四行字节码组成,探针不改变该代码的行为,只记录他们是否已被执行,从理论上讲,可以在每行代码都插入一个探针,但是探针本身需要多个字节码指令,这将增加几倍的类文件的大小和执行速度,所以JaCoCo有一定的插桩策略。

ALOAD    probearray
xPUSH    probeid
ICONST_1
BASTORE

探针插桩策略

探针的插入需要遵循一定策略,大体可分成以下三个策略:

  • 统计方法的执行情况。

  • 统计分支语句的执行情况。

  • 统计普通代码块的执行情况。

 

方法的执行情况

这个比较容易处理, 在方法头或者方法尾加就可以了。

  • 方法尾加: 能说明方法被执行过, 且说明了探针上面的方法被执行了,但是这种处理比较麻烦, 可能有多个return或者throw。

  • 方法头加: 处理简单, 但只能说明方法有进去过。

通过分析源码,发现JaCoCo是在方法结尾处插入探针,retrun和throw之后都会加入探针。

  public void visitInsn(final int opcode) {
    switch (opcode) {
    case Opcodes.IRET
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值