JaCoCo助您毁灭线上僵尸代码 | 京东物流技术团队

news2024/11/27 20:36:17

一. 现状·问题

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

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

二. 分析原因

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

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

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

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

•······

三. 采取措施

问产品经理哪些能下线?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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/875441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文讲透!请收下这份“完美”地图贴图的制作攻略

3D渲染中&#xff0c;我们称传入材质的纹理为贴图。贴图一词强调其用途&#xff0c;当某个纹理用于在材质中实现法线效果时&#xff0c;我们称之为法线贴图。而在EasyV中&#xff0c;我们地图组件填充样式中的自定义上传的图片称之为「地图贴图」&#xff0c;主要用于地图表面/…

多线程进阶

多线程进阶 本章博客主要是围绕一些多线程相关的面试题&#xff0c;讨论的内容都是往年同学遇到的原题&#xff0c;以后面试也大概率会遇到的&#xff01;&#xff01;&#xff01; 常见的锁策略 锁策略指的不是某个具体的锁&#xff0c;是一个抽象的概念&#xff0c;描述的…

VS2019 设置注释和取消注释选选定内容

Microsoft Visual Studio Professional 2019 由于老是忘记&#xff0c;换了电脑就不行了&#xff0c;原来默认的太繁琐。 每次都去设置选定内容&#xff0c;老是不行。 应该设置在切换块注释 上面这样就可以按一个组合键实现注释和不注释了。

考研408 | 【计算机网络】 传输层

导图 传输层的功能 传输层的两个协议 传输层的寻址与端口 UDP协议 UDP的主要特点 UDP首部格式&#xff1a; UDP校验&#xff1a; TCP协议 TCP协议的特点 TCP报文段首部格式 TCP连接管理 TCP的连接建立 SYN洪泛攻击 TCP的连接释放 TCP可靠传输 序号&#xff1a; 确认&#xff1…

【Rust】Rust学习 第十二章一个 I/O 项目:构建一个命令行程序

本章既是一个目前所学的很多技能的概括&#xff0c;也是一个更多标准库功能的探索。我们将构建一个与文件和命令行输入/输出交互的命令行工具来练习现在一些你已经掌握的 Rust 技能。 Rust 的运行速度、安全性、单二进制文件输出和跨平台支持使其成为创建命令行程序的绝佳选择…

回归预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现L…

C++ 动态规划经典案例解析之最长公共子序列(LCS)_窥探递归和动态规划的一致性

1. 前言 动态规划处理字符相关案例中&#xff0c;求最长公共子序列以及求最短编辑距离&#xff0c;算是经典中的经典案例。 讲解此类问题的算法在网上一抓应用一大把&#xff0c;即便如此&#xff0c;还是忍不住有写此文的想法。毕竟理解、看懂都不算是真正掌握&#xff0c;唯…

侯捷 C++ part2 兼谈对象模型笔记——6 多态 虚机制

6 多态 虚机制 6.1 虚机制 当类中有虚函数时&#xff08;无论多少个&#xff09;&#xff0c;其就会多一个指针—— vptr 虚指针&#xff0c;其会指向一个 vtbl 虚函数表&#xff0c;而 vtbl 中有指针一一对应指向所有的虚函数 有三个类依次继承&#xff0c;其中A有两个虚函…

​LeetCode解法汇总617. 合并二叉树

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你两棵二…

智能制造感知产品在工业4.0中的应用

在工业4.0时代&#xff0c;智能制造已经成为制造行业的重要发展方向。智能制造感知产品作为智能制造的核心组成部分&#xff0c;对于提高制造效率、降低成本、提升产品质量等方面具有重要的作用。本文将详细介绍智能制造感知产品在工业4.0中的应用。 智能制造感知产品在工业4.…

磁场是灵魂散发出来的力量

为什么有些人的思维很敏捷&#xff0c;但是&#xff0c;到了另外一个人面前&#xff0c;他的思维会突然错乱或停顿了呢&#xff1f; 每一个人的磁场都有一种释放和吸收的功能&#xff0c;如果经常和磁场比较污浊的人接触&#xff0c;他也会把我们的磁场给染污了。如果跟一个磁场…

IDEA部署配置Maven项目教程,IDEA配置Tomcat(2019.3.3)(2023.1.3)

我们往往会用到多版本的IDEA进行一个Maven项目配置部署&#xff0c;还有tomcat的配置&#xff0c;这里就有你需要的&#xff0c;有低版本的&#xff0c;也有高版本的&#xff0c;根据自己的情况来进行一个操作 一、前言 当涉及到软件开发和项目管理时&#xff0c;使用一个可靠的…

iPhone恢复备忘录的4种方法!超好用!

iPhone备忘录能够帮助我们记录一些重要的事务或者个人事项&#xff0c;帮助减少遗漏和失误。小编也常常使用iPhone备忘录来记录事情&#xff0c;避免自己忘记。但有时候可能会因为自己的操作失误&#xff0c;导致备忘录误删除或丢失&#xff0c;那么这时候该怎么办呢&#xff1…

电子行业精密空调监控,这个方法非常全面!

在电子行业&#xff0c;精密空调监控扮演着至关重要的角色。电子设备的制造、储存和运行过程中&#xff0c;恒定的环境条件如温度、湿度和空气质量对于确保设备的高效运行和稳定性至关重要。 由于许多电子元件对环境变化极为敏感&#xff0c;因此精密空调监控成为了维护产品质量…

使用UDP协议实现—翻译服务器

目录 前言 1.设计思路&#xff1a; 2.词库设计 3.设计客户端 4.设计服务端 5.编译客户端和服务端 6.测试结果 7.总结 前言 上一篇文章中&#xff0c;我们使用UDP协议编码完成了一个简单的服务器&#xff0c;实现数据通信&#xff0c;服务器设计出来后目的不仅仅只是实现…

C#软件外包开发框架

C# 是一种由微软开发的多范式编程语言&#xff0c;常用于开发各种类型的应用程序&#xff0c;从桌面应用程序到移动应用程序和Web应用程序。在 C# 开发中&#xff0c;有许多框架和库可供使用&#xff0c;用于简化开发过程、提高效率并实现特定的功能。下面和大家分享一些常见的…

VeraCard已经上线了 — 快来领取你的吧!

VeraCard现在已经可以订购&#xff0c;并为英国居民积极发货&#xff01;VeraCard是一张Visa借记卡&#xff0c;是我们与DAMEX合作推出的。Verasity是在DAMEX上列出的第一个替代币&#xff0c;并且是第一个拥有自己品牌卡片的代币。有了VeraCard&#xff0c;Verasity社区成员现…

OpenCV图像处理——形态学操作

目录 连通性形态学操作腐蚀和膨胀开闭运算礼帽和黑帽 连通性 形态学操作 形态学转换是基于图像形状的一些简单操作。它通常在二进制图像上执行。腐蚀和膨胀时两个基本的形态学运算符。然后它的变体形式如开运算&#xff0c;闭运算&#xff0c;礼帽黑帽等 腐蚀和膨胀 cv.erode…

OSI七层模型和TCP/IP四层模型

OSI七层模型和TCP/IP四层模型 七层模型(OSI) OSI七层模型&#xff08;Open Systems Interconnection Reference Model&#xff09;是一个用于计算机网络体系结构的标准化框架&#xff0c;旨在定义网络通信中不同层次的功能和协议。 各个层次具体如下&#xff1a; 物理层&am…

【Spring专题】Spring之Bean的生命周期源码解析——阶段一(扫描生成BeanDefinition)

目录 前言阅读准备阅读指引阅读建议 课程内容一、生成BeanDefinition1.1 简单回顾*1.2 概念回顾1.3 核心方法讲解 二、方法讲解2.1 ClassPathBeanDefinitionScanner#scan2.2 ClassPathBeanDefinitionScanner#doScan2.3 ClassPathScanningCandidateComponentProvider#findCandid…