1、现状痛点
系统越来越臃肿,开发过程中可能产生的无用代码增加了系统维护成本。
2、设计思路
2.1、静态代码扫描方案
本方案解决静态代码下无调用方法扫描,通过ASTParser对静态文件进行扫描分析,获取代码块来判断调用关系。
基本步骤及思路
(1)载入本地磁盘项目
(2)循环使用ASTParser解析每个java文件的方法块,把类名+方法名和方法代码块一起落缓存,vm文件单独落。
分析代码如下

(3)进行调用关系扫描,再次用ASTParser解析解析每个java文件的方法块,拿方法名去缓存中根据代码块模糊查询,刨除掉自己之后统计调用次数,次数为0的可以认为是僵尸方法,打印出来供参考。
2.2、运行时扫描方案
本方案是借助jacoco(Java Code Coverage),jacoco本质是一种测试覆盖率工具,通过asn字节码增强技术再源代码中加入探针从而获取代码覆盖率
具体实践
(1)依赖jacoco.ant
在工程内的pom中引入jar依赖
1<dependency> 2 <groupId>org.jacoco</groupId> 3 <artifactId>org.jacoco.ant</artifactId> 4 <version>0.8.3</version> 5</dependency> 6<dependency> 7 <groupId>org.apache.ant</groupId> 8 <artifactId>ant</artifactId> 9 <version>1.9.9</version> 10 </dependency>
(2)赋能Rest请求
添加一个url地址,通过ant执行dump task用于Dump Coverage文件生成
1@RestController 2@RequestMapping("/coverage") 3public class CoverageController { 4 5 @PostMapping("dump") 6 @NoCheckMenuPermission 7 public Result<Boolean> dumpCoverageFile() { 8 DumpTask dumpTask = new DumpTask(); 9 // dump文件地址 10 dumpTask.setDestfile(new File("/export/Data/coverage/code-cover.exec")); 11 // 多次dump追加形式 12 dumpTask.setAppend(true); 13 // 选一个空闲接口即可 14 dumpTask.setPort(8840); 15 // 默认本机 16 dumpTask.setAddress("127.0.0.1"); 17 dumpTask.execute(); 18 return Result.succeed(true); 19 } 20}
(3)嵌入jacocoagent
java启动参数添加如下:
1#decompress file 解压依赖,获得jacocoagent.jar包,避免需要联系运维上传包 2jar -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
(4)增加配置脚本
/home/admin/clean_export.sh( 脚本默认内容上增加了 *&& $9 != "coverage" *)
输出的文件路径为 /export/Data/coverage/code-cover.exec
(5)下载cover文件
/export/Data/coverage/code-cover.exec目录下
(6)分析代码
打开idea -> run -> show coverage data选择对应的exec文件即可获取服务端的代码覆盖情况。
绿色覆盖(活跃代码)

红色未覆盖(僵尸代码)

(7)相关链接
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
3、实现结果
1、启动工具,选择工程路径

2、点击生成DB,解析代码载入数据库


3、点击扫描,获取结果

