JaCoCo探针策略原理及案例总结

简介: JaCoCo探针策略原理及案例总结

1 探针策略

  • 在一串字节码指令中插入这些探针,只要该探针被执行了,说明其之前的指令都被执行了
  • 1.png
  • 2.png
  • 注意方法结束了是在 return 指令前放置探针哦
  • 3.png
  • 跳转语句的记录
  • 4.png
  • 条件语句
  • 5.png
  • 6.png

2 探针特点

探测的唯一目的是记录它至少执行过一次。探测器不记录它被调用的次数或收集任何时间信息。后者超出了代码覆盖率分析的范围,更多的是在性能分析工具的目标中

  • 最小的运行时间开销
  • 对应用程序代码无副作用
  • 线程安全
  • 记录字节码的执行
  • 标识不同类型探针
    使用的 boolean 数组记录对应的指令是否被执行

3 为什么最小的性能开销?

7.png

javap -c Fun

...
       0: getstatic     #2                  // Field $assertionsDisabled:Z
       3: ifne          18
       6: iload_1
       7: ifne          18
      10: new           #3                  // class java/lang/AssertionError
      13: dup
      14: invokespecial #4                  // Method java/lang/AssertionError."<init>":()V
      17: athrow
      18: return
...

其实翻译过来代码就是这样子

8.png

通过将这种原理用于 jacoco,降低了性能开销

9.png

4 如何实现代码注入

image.png

JaCoCo通过ASM在字节码中插入Probe指针(探测指针),每个探测指针都是一个BOOL变量(true表示执行、false表示没有执行),程序运行时通过改变指针的结果来检测代码的执行情况(不会改变原代码的行为).

增量注入

JaCoCo默认全量注入.

源码中注入的逻辑主要在ClassProbesAdapter

11.png

ASM在遍历字节码时,每次访问一个方法定义,都会回调这个类的visitMethod方法 ,在visitMethod方法中再调用ClassProbeVisitorvisitMethod方法,并最终调用MethodInstrumenter完成注入。部分代码片段如下:

@Override
public final MethodVisitor visitMethod(final int access, final String name,
    final String desc, final String signature,
    final String[] exceptions) {
  final MethodProbesVisitor methodProbes;
  final MethodProbesVisitor mv = cv.visitMethod(access, name, desc,
      signature, exceptions);
  if (mv == null) {
    // 无论如何,我们都需要访问该方法,否则探针的ID无法重现
    methodProbes = EMPTY_METHOD_PROBES_VISITOR;
  } else {
    methodProbes = mv;
  }
  return new MethodSanitizer(null, access, name, desc, signature,
      exceptions) {
    @Override
    public void visitEnd() {
      super.visitEnd();
      LabelFlowAnalyzer.markLabels(this);
      final MethodProbesAdapter probesAdapter = new MethodProbesAdapter(
          methodProbes, ClassProbesAdapter.this);
      if (trackFrames) {
        final AnalyzerAdapter analyzer = new AnalyzerAdapter(
            ClassProbesAdapter.this.name, access, name, desc,
            probesAdapter);
        probesAdapter.setAnalyzer(analyzer);
        methodProbes.accept(this, analyzer);
      } else {
        methodProbes.accept(this, probesAdapter);
      }
    }
  };
}

自动获取运行时数据

代码中通过反射执行下面的函数来获取运行时数据,并保存到当前执行代码的设备中:

org.jacoco.agent.rt.RT.getAgent().getExecutionData(false)

生成报告时需要用到运行时数据,为了生成的覆盖率报告更准确、开发同学用起来更方便,分别在如下时机把运行时数据保存到当前设备中:


每个页面执行onDestory时

程序发生崩溃时

收到特定广播(一个自定义的广播,在执行生成覆盖率报告的task前发送)时

并在生成覆盖率报告之前把设备中的运行时数据同步到本地开发环境中。


上面可以看到,因为获取时机比较多,可能会得到多份运行时数据,对于这些数据,可以通过JaCoCo的mergeTask把ClassId相同的运行时数据进行merge。如下图所示,JaCoCo会对ClassId相同的运行时数据进行merge,并对相同位置的probe指针取或:

12.png


目录
相关文章
|
jenkins Java 应用服务中间件
代码覆盖率工具-jacoco环境搭建分享
Web多个服务在docker中启动,服务之间存在依赖关系,启动端口号以及依赖的镜像关系都配置在docker-compse.yml文件中。需要借助代码覆盖率工具,对后端Java代码进行覆盖率统计。
代码覆盖率工具-jacoco环境搭建分享
|
2月前
|
人工智能 JSON 监控
三步构建AI评估体系:从解决“幻觉”到实现高效监控
AI时代,评估成关键技能。通过错误分析、归类量化与自动化监控,系统化改进AI应用,应对幻觉等问题。Anthropic与OpenAI均强调:评估是产品迭代的核心,数据驱动优于直觉,让AI真正服务于目标。
328 8
|
中间件 Linux vr&ar
Centos7升级Glibc
Centos7升级Glibc
1886 6
|
XML 监控 负载均衡
Jacoco的覆盖率原理
JaCoCo(Java Code Coverage)是一种广泛使用的代码覆盖率工具,通过在字节码中插入探针(Probe)来收集覆盖率信息。
1043 6
Jacoco的覆盖率原理
|
9月前
|
资源调度 监控 JavaScript
使用Yarn创建Grafana模板的完整指南
本文介绍如何使用Yarn生成Grafana模板,涵盖从安装Node.js和Yarn到创建并验证Grafana仪表板的全过程。具体步骤包括:1) 安装Node.js和Yarn;2) 创建Yarn项目;3) 安装Grafana API客户端库;4) 编写模板脚本;5) 生成模板文件;6) 在Grafana中加载并验证模板。通过详细的代码示例和流程图,帮助你轻松完成这一过程。
459 0
|
存储 SQL 测试技术
基于SpringBoot+Vue入校申报审批系统的设计与实现(源码+部署说明+演示视频+源码介绍+lw)(2)
基于SpringBoot+Vue入校申报审批系统的设计与实现(源码+部署说明+演示视频+源码介绍+lw)
349 1
|
存储 安全 网络协议
epoll的底层实现原理
epoll的底层实现原理
245 0
|
测试技术 Apache
使用 Apache JMeter Flexible File Writer 插件的详细指南
Apache JMeter 是开源性能测试工具,用于负载测试。Flexible File Writer 是一个插件,用于自定义格式记录测试结果。安装该插件需通过 JMeter 的 Plugins Manager。配置时,添加监听器到测试计划,设置输出文件、文件格式及字段。执行测试后,结果将按指定格式写入 CSV 文件。此插件增强了数据记录的灵活性,便于分析和报告。
|
前端开发 JavaScript IDE
WebStorm 打开多个项目的方法
【2月更文挑战第1篇】
1277 2
|
运维 安全 数据处理
运维服务体系架构
【2月更文挑战第28天】构建数据中心的IT运维服务体系,需整合资源,规范行为,确保服务质量。该体系基于ITIL和ITSS标准,全面覆盖IT服务生命周期和业务类型,统筹规划并保持科学权威。体系由制度、流程、组织、队伍、技术平台和运维对象六部分组成,制度规定流程,组织和人员遵循制度执行标准化运维。重点包括运维服务制度与流程的制定、专业团队的建设和统一的工作流程,以及运用技术平台进行规范化管理。