JAVA覆盖率统计之01-Jacoco控制流案例
2018-07-01 本文已影响32人
antony已经被占用
字节码注入与控制流
1 注入方式
JaCoCo是一个被广泛使用的JAVA覆盖率统计工具,它利用ASM库,通过注入字节码的方式来修改和生成java字节码,从而记录程序的执行数据,但它不会改变原有代码的行为。 最常用的方式是通过Java Agent以On-The-Fly的方式在runtime来注入和统计数据。这种方式就不会改变编译的class文件。
implementation.png
当然在本文中,笔者将介绍Jacoco的具体注入方式,因此,我们使用Jaccoco Offline 的模式,在编译时直接将覆盖率统计的探针(Probe)注入(Inject)到被打桩的class文件中。
2 Probe探针组成
Jacoco是通过一个Probe探针的方式来注入的,探针是字节指令集插入到java方法中,程序执行后可以被记录,它不会改变原有代码的行为。
根据Jacoco官方介绍,一个Probe可以由以下JVM指令组成:
JVM指令 | Probe作用 | 说明 |
---|---|---|
ALOAD | probearray | 将一个引用类型本地变量推送至栈顶 |
xPUSH | probeid | 将一个常量值推送至栈顶 |
ICONST_1 | 将int型推送至栈顶 | |
BASTORE | 从操作数栈存存储到数组 |
根据代码逻辑的不同,可以由如下的一些变化:
Possible Opcodes | Min. Size [bytes] | Max. Size [bytes] |
---|---|---|
ALOAD_x, ALOAD * | 1 | 2 |
ICONST_x, BIPUSH, SIPUSH, LDC, LDC_W ** | 1 | 3 |
ICONST_1 | 1 | 1 |
BASTORE | 1 | 1 |
Total: | 4 | 7 |
- The probe array is the first variable after the arguments. If the method arguments do not consume more that 3 slots the 1-byte opcode can be used.
** 1-byte opcodes for ids 0 to 5, 2-byte opcode for ids up to 127, 3-byte opcode for ids up to 32767. Ids values of 32768 or more require an additional constant pool entry. For normal class files it is very unlikely to require more than 32,000 probes.
感兴趣的读者可以阅读以下链接了解更多
3 Probe探针插入策略
JaCoCo是根据控制流Type来采用不同的探针插入策略的。探针不改变该方法的行为,但记录他们已被执行的事实,从理论上讲,可以在控制流图的每一个边插入一个探针,作为探针实现本身需要多个字节码指令,这将增加几倍的类文件的大小和执行速度。事实上,只需要一个几个探头,根据每个方法的控制流的方法。具体策略如下:
jump.JPG
return.JPG
案例
以下案例来介绍IF/FOR/抛异常等场景下jacoco是如何进行注入的。
package com.demo.jacoco;
public class DemoClass {
public static void callIf(boolean flag) {
print("start");
if(flag) {
print("true");
}else {
print("flase");
}
print("done");
}
private static void print(String string) {
System.out.println(string);
}
public static void callFor(int loop) {
for(int i=0;i<loop;i++)
print("hi");
}
public static void callThrow(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我们通过javap 来解析DemoClass.class
javap -v -c DemoClass.class
1 IF
![](https://img.haomeiwen.com/i2651525/0a155f5b1d9281a4.JPG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)2 FOR
jacoco_for.JPG3 Throw
jacoco_throw.JPG4 默认构造方法
jacoco_1类构造方法.JPG