jacoco有对类级别,方法级别,逻辑分支级别以及代码行级别做了专门的处理封装。具体的封装类在internal.analysis.flow
1 IFrame 接口
import org.objectweb.asm.MethodVisitor; /** * 当前的 stackmap frame 内容的表示 */ public interface IFrame { /** * 向给定的访问者发出具有当前内容的 frame 事件 * * @param mv 向该方法发出 frame 事件的method visitor */ void accept(MethodVisitor mv); }
涉及的类分别是ClassprobesAdapter.java(类级别),Instruction.java(指令级别),LabelFlowAnalysis.java(逻辑分支级别)和MethodProbesAdapter.java(方法级别)。
2 ClassprobesAdapter
一个 org.objectweb.asm.ClassVisitor,它为每个方法计算探针.
属性
private static final MethodProbesVisitor EMPTY_METHOD_PROBES_VISITOR = new MethodProbesVisitor() { }; // The class visitor to which this visitor must delegate method calls. May be null // 委托的实例,该访问者必须委派方法调用的类访问者。 可能为null private final ClassProbesVisitor cv; // 如果为true,跟踪并提供 stackmap frames private final boolean trackFrames; private int counter = 0; private String name;
visitMethod
publicfinal MethodVisitor visitMethod(intaccess, String name, String desc, String signature, String[] exceptions) { MethodProbesVisitor mv =this.cv.visitMethod(access, name, desc, signature, exceptions); MethodProbesVisitor methodProbes; final MethodProbesVisitor methodProbes; if (mv == null) { methodProbes =EMPTY_METHOD_PROBES_VISITOR; } else { methodProbes = mv; } new MethodSanitizer(null, access, name,desc, signature, exceptions) { public void visitEnd() { super.visitEnd(); LabelFlowAnalyzer.markLabels(this); MethodProbesAdapter probesAdapter = newMethodProbesAdapter(methodProbes, ClassProbesAdapter.this); if(ClassProbesAdapter.this.trackFrames) { AnalyzerAdapter analyzer = new AnalyzerAdapter(ClassProbesAdapter.this.name,this.access, this.name, this.desc, probesAdapter); probesAdapter.setAnalyzer(analyzer); accept(analyzer); } else { accept(probesAdapter); } } }; }
可见类覆盖率字节码埋入实际上是对类中每一个方法和每一个逻辑分支做埋入,只要记录调用类中方法的覆盖代码行,自然类的覆盖就会被统计到。
3 ClassProbesVisitor 抽象类
具有附加方法的 ClassVisitor,可获取每种方法的探针插入信息
/** * 当访问一个方法时,我们需要一个 MethodProbesVisitor 来处理该方法的探测 */ @Override public abstract MethodProbesVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions);