JaCoCo助您毁灭线上僵尸代码

2023-11-08

一. 现状·问题

随着需求不断迭代,业务系统的业务代码突飞猛进,在你自豪于自己的代码量产出很高时,有没有回头看看线上真正的客户使用又有多少呢?

费事费力耗费大量人力,成本上线的功能,可能一年没人使用,如果不进行适当的下线,就会增加系统维护成本,此时就需要计划删除无用代码。但是我们怎么知道真实线上的一行行代码层面,是否真实在使用,或者真实没人用,怎么可以放心删除下线功能呢!

二. 分析原因

实际上多数业务系统都会存在这个通病:线上僵尸代码

•可能是前期产品对业务场景没有分析到位

•可能是研发期间需求功能偏离了正确方向

•可能是上线后因外界因素使客户业务量下降

•······

三. 采取措施

问产品经理哪些能下线?NO 没人敢承诺

观测 UMP接口是否有流量?NO 只知道接口维度,有流量的接口难道所有代码都有用么

使用jacoco(Java Code Coverage)进行线上代码分析,对系统做瘦身。

Jacoco本质上是一个测试覆盖率工具,通过ASM字节码增强技术在源代码中加入探针从而获取代码覆盖率。Jacoco主要是通过Jave agent在main函数执行之前通过指定方法在执行的代码中加入探针来记录代码是否被执行过。

Java agent是Java提供的一个启动参数,有别于代理方式的动态增强和annotation processor的编译时增强,该参数通过指定路径的jar包中的premain方法将在main方法执行之前被调用增强源代码,通过实现该方法我们可以对加载的Class文件进行修改源代码增强,使用此技术的还有大部分APM工具。

https://www.jacoco.org/jacoco/trunk/doc/index.html

四. 实践步骤

4.1 依赖jacoco.ant

在工程内的pom中引入jar依赖

<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.ant</artifactId>
    <version>0.8.3</version>
</dependency>
<dependency>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant</artifactId>
     <version>1.9.9</version>
 </dependency>


4.2 赋能Rest请求

添加一个url地址,通过ant执行dump task用于Dump Coverage文件,避免使用配置文件且同时需要运维同事帮忙操作的问题。

@RestController
@RequestMapping("/coverage")
public class CoverageController {

    @PostMapping("dump")
    @NoCheckMenuPermission
    public Result<Boolean> dumpCoverageFile() {
        DumpTask dumpTask = new DumpTask();
        // dump文件地址
        dumpTask.setDestfile(new File("/export/Data/coverage/code-cover.exec"));
        // 多次dump追加形式
        dumpTask.setAppend(true);
        // 选一个空闲接口即可
        dumpTask.setPort(8840);
        // 默认本机
        dumpTask.setAddress("127.0.0.1");
        dumpTask.execute();
        return Result.succeed(true);
    }
}


4.3 嵌入jacocoagent

由于jacoco需要在服务端由jacocoagent增强的jar包,为了避免需要麻烦运维同事,通过maven依赖我们可以发现org.jacoco.agent这个jar包中包含由jacocoagent这个包,所以通过在部署的启动脚本添加以下命令即可通过解压的方式获得该jar包!

java启动参数添加如下:存在多个javaagent时比如pfinder之类在其后添加即可。

#decompress file 解压依赖,获得jacocoagent.jar包,避免需要联系运维上传包
jar -xvf $BASEDIR/lib/org.jacoco.agent-0.8.3.jar


-javaagent:$BASEDIR/bin/jacocoagent.jar=includes=com.jdwl.*,output=tcpserver,port=8840,address=127.0.0.1 -Xverify:none


premain方法中我们可以通过Instrumention的addTransformer添加ClassFileTransformer接口的实现类,该接口中仅有一个方法如下,通过实现ClassTransformer我们可以定义自己的代码增强方法。可以使用ASM,亦可以使用javasist等高级类库。

相关实践:Diving Into Bytecode Manipulation: Creating an Audit Log With ASM and Javassist | New Reli

4.4 JDOS资源预留

资源预留/export目录自定义处理

  • 增加配置脚本 /home/admin/clean_export.sh(脚本默认内容上增加了 && $9 != “coverage”

输出的文件路径为/export/Data/coverage/code-cover.exec

#! /bin/bash

ls -lh /export | awk 'NR >1 {print}' | awk '{if ($9 != "Data") print $9}' | xargs -i /bin/rm -rf /export/{} > /dev/null 2>&1
ls -lh /export/Data | awk 'NR >1 {print}' | awk '{if ($9 != "jdos.jd.com" && $9 != "coverage") print $9}' | xargs -i /bin/rm -rf /export/Data/{} > /dev/null 2>&1


4.5 下载cover文件

/export/Data/coverage/code-cover.exec

登录堡垒机终端

 cd /export/Data/coverage

jdos下载文件

 curl -s up.bastion.jd.com/file/up | bash

4.6 分析代码

打开idea -> run -> show coverage data选择对应的exec文件即可获取服务端的代码覆盖情况。

绿色覆盖(活跃代码)

红色未覆盖(僵尸代码)

Reference

  1. JaCoCo - Documentatio
  2. javaagent使用指南 - rickiyang - 博客园 (cnblogs.com
  3. 使用Jacoco统计服务端代码覆盖情况实践 - M104 - 博客园 (cnblogs.com
  4. Diving Into Bytecode Manipulation: Creating an Audit Log With ASM and Javassist | New Reli

五. 效能提升

5.1 需求交付效率提升

5.1.1 缩短需求交付周期

因为僵尸代码删除,减少开发需求的范围,降低老代码认知成本,降低测试回归成本。

需求交付周期整体呈缩短趋势!2023/1月落地实践,之前需求交付周期约15天,之后约12天。

5.1.2 降低开发阶段停留时长

僵尸代码大量存在,研发认知需求改动点负荷很高,需要耗费大量时间成本。

2023/1月落地后,开发阶段时长缩短到 4天 以下(由 4.54 缩短至 3.11,缩短约31%),呈明显缩短趋势!

5.2 人效提升

5.2.1 降低研发认知负荷

删除无用僵尸代码,圈复杂度会大幅度降低,重复代码块也会降低,则研发认知负荷也会随之降低!

平均系统重复代码块数从 31 下降至 27 左右,降低了系统维护成本!

5.2.2 提升人均需求吞吐量

因为减少人力认知成本,缩小需求范围,所以会直接提升需求的吞吐量!

自从2023/1月落地实践后,人均需求的吞吐量也大幅度提升,从之前 1.5 提升到 2.5 左右。

5.3 过程质量提升

5.3.1 减少自动化bug数

由于存量僵尸代码减少,则整体回滚用例和场景变得精简,黄金流程也不会被僵尸代码干扰,则自动化bug数也有明显下降趋势

随着2023年1月以来的不断实践,自动化发现的bug数也逐月递减,从11个/月 -> 9个/月 -> 6个/月 -> 5个/月。

5.3.2 提升单测覆盖率

自从2023年1月落地实践后,随着删除掉大量僵尸代码,整体代码总量在减少,无效代码被无情下线,同时提升了单测代码覆盖率,呈上升趋势单测行覆盖率从 51.33% -> 52.28%,提升系统质量!

六. 简要总结

  • 随着需求不断迭代交付,业务代码必然不断累积,运维成本不断升高,如果线上无用功能的代码一直残留,对研发来说是巨大的累赘!对于此类代码约定俗成为 “僵尸代码”
  • 赶快利用jacoco探针深入分析系统的一行行代码,看到线上功能运行最真实的一面,参照代码的覆盖情况,针对性下线和删除僵尸代码,让系统瘦身,让研发减负!

作者:京东物流 周奕儒

来源:京东云开发者社区 自猿其说Tech

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JaCoCo助您毁灭线上僵尸代码 的相关文章

随机推荐

  • angular 基础入门总结

    工程文件创建和依赖下载 依赖npm工具 npm用来对node js的模块进行管理 主要2个用途 下载别人编写的第三方包到本地使用 上传自己的包供别人使用 package json 执行npm init 可以根据提示生成包描述文件 就是自己包
  • 054-机械臂编程

  • JavaScript 数组(数组的增删和数组排序)

    一 数组方法 1 数组操作 push 向数组末尾添加元素 返回新数组长度 添加单个元素 let arr JS Java C let newArrLength arr push PHP console log arr JS Java C PH
  • 基于量子粒子群算法(QPSO)优化LSTM的风电、负荷等时间序列预测算法(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 本文基于QPSO LSTM算法进行负荷 光
  • 功能测试和非功能测试有什么区别?

    转载 https dzone com articles whats the difference between functional and nonfun fromrel true 功能测试验证功能是否按照要求工作 而非功能测试则对更广泛
  • 通信加密与解密

    一 通信加密和解密技术概述 1 1 Bob和Alice的爱情故事 早些年间 恋人们之间的交往以书信沟通较为频繁 在那个年代 这种恋爱的人叫笔友 假设Bob和Alice正是处于这一时代 Bob和Alice恋爱了 他们两个好不容易走到一起 可是
  • 顺序表的简单操作代码(c++实现)

    include
  • HDU 4731 Minimum Palindrome

    hdu 4731 Minimum palindrome 题意 前n个字母形成一个m长的字符串 要求如下 1 最长回文串最小 2 字典序最小 思路 1 n 1 aaaa 2 n 2 打表找规律 1 a 2 ab 3 aab 4 aabb 5
  • 深度优先与宽度优先搜索(python)

    算法原理 1 宽度优先搜索 宽度优先搜索算法 Breadth First Search BSF 思想是 从图中某顶点v出发 首先访问顶点v 在访问了v之后依次从左往右访问v的各个未曾访问过的邻接点 然后分别从这些邻接点出发依次从左往右访问它
  • 引用文档-软件测试分类及测试中三个主要概念

    软件测试分类及测试中三个主要概念 原文链接 https blog csdn net qq 35867537 article details 77477775 1 软件测试分类 按测试技术分 按测试技术 软件测试可分为 黑盒测试 白盒测试 灰
  • 手撕八大排序(上)

    排序的概念及其引用 排序的概念 排序 所谓排序 就是使一串记录 按照其中的某个或某些关键字的大小 递增或递减的排列起来的操作 稳定性 假定在待排序的记录序列中 存在多个具有相同的关键字的记录 若经过排序 这些记录的相对次序保持不变 即在原序
  • vue富文本编辑器中上传图片

    啊 好久没更新了 最近粉丝和访问量见长 正好有童鞋的项目遇到点问题 故出此文 今天超哥给小伙伴带来的是vue中富文本编辑器上传的问题 曾经写过一个文档管理的项目 用到最多的就是富文本编辑器 说说遇到的坑吧 最终的提交结果 后端不要文档流 后
  • jmap命令(Java Memory Map)

    JDK内置工具使用 一 javah命令 C Header and Stub File Generator 二 jps命令 Java Virtual Machine Process Status Tool 三 jstack命令 Java St
  • 华为机试-python

    HJ97 首先输入要输入的整数个数n 然后输入n个整数 输出为n个整数中负数的个数 和所有正整数的平均值 结果保留一位小数 while True try n int input count1 0 count2 0 sum 0 0 for i
  • 小白spss学习笔记(二)

    SPSS初学笔记 二 1 单因素方差分析 对三组或三组以上独立样本的均数差异性的比较用单因素方差分析 所谓方差分析就是对多个平均数进行比较的一种统计方法 又称变异数分析 其主要功能在于分析实验数据中不同来源的变异对总变异的贡献大小 从而确定
  • TCP详解之三次握手、四次挥手

    在互联网很多岗位的面试中TCP的三次握手 四次挥手都是不可绕过的话题 有很高的热点度 今天我就带大家来看看什么是三次握手 四次挥手 在讲之前 我们先来了解下TCP协议是什么 1 TCP协议 TCP协议全称 传输控制协议 顾名思义 就是要对数
  • “伶荔(Linly)”项目团队全新发布中文Falcon基础模型

    引言 近期 阿联酋阿布扎比的技术创新研究所 TII 开源了 Falcon 系列模型 使用经过筛选的 1 万亿 tokens 进行预训练 并以 Apache 2 0 协议开源 可能是目前效果最好且许可协议最宽松 允许商用 的开源模型 然而 F
  • 【QT开发笔记-基础篇】

    本节对应的视频讲解 B 站 链 接 https www bilibili com video BV1mN4y137H6 信号和槽要建立连接 本质上是通过 connect 函数来连接实现的 但是从写法或者操作上来说 有多种方式 以下总结了 5
  • qsort用法

    轉自 http www cnblogs com ForeverJoker archive 2013 05 25 qsort sort html qsort函数 sort函数 精心整理篇 qsort函数 sort函数 精心整理篇 先说明一下q
  • JaCoCo助您毁灭线上僵尸代码

    一 现状 问题 随着需求不断迭代 业务系统的业务代码突飞猛进 在你自豪于自己的代码量产出很高时 有没有回头看看线上真正的客户使用量又有多少呢 费事费力耗费大量人力 成本上线的功能 可能一年没人使用 如果不进行适当的下线 就会增加系统维护成本