项目开发中遇到了一个问题,类中出现未知属性 ‘ $jacocoData ’,准确的来讲,实际上在集成测试阶段,系统自动运行测试用例时,抛出来的异常提示信息,可是在开发阶段是不存在的。这个问题是之前没有遇到过的一中bug,所以在此处记录并分析。java
(与本片无关,介意者忽略)框架
先在这儿介绍一下目前项目的开发模式,使用的是迭代式开发。(参考百度)jvm
1.瀑布式开发: 瀑布模型式是最典型的预见性的方法,严格遵循预先计划的需求、分析、设计、编码、代码审阅、测试、维护的步骤顺序进行。maven
适用:系统目标需求明确,时间固定,函数
2.敏捷式开发:敏捷开发以用户的需求进化为核心,采用迭代、按部就班的方法进行软件开发。敏捷式开发是一种开发方法。工具
适用:以用户为导性,快速开发,验证,修正的一种开发方式。单元测试
3. 迭代式开发:在迭代开发中,整个开发工做被组织为一系列的短小的、固定长度(如3周)的小项目,被称为一系列的迭代,这叫迭代开发。测试
每一次迭代都包括了定义、需求分析、设计、实现与测试。迭代式开发是一种开发过程。编码
适用:需求不明确,持续进行变动的项目,能够下降风险,提升复用性。spa
目前fn先生所开发项目的相关步骤:
1. 任务需求:由PD产出需求,分析以后,明确本次迭代的checkList;
2. 文档编写:由开发/测试共同编写,其中需求背景,开发思路,系统交互,接口文档,测试场景,上线时间,人员排期及FAQ等;
3. 项目阶段:开发阶段 -> 集成测试 -> 预发灰度 ->项目上线;
注:在开发完成时,须要有交付报告产出,代表本次开发的影响点,风险点,上线时间,jar发布版本,系统间交互影响,是否可回滚等等;
4. 下个需求:哎,惆怅,轮番轰炸呐!!!头发都快成C字型了。
(正文)
如题,所遇到的状况是:
类说明:继承多层级的抽象类,其下有多个子类,其中有一type属性对应该类的类型,还有一个属性properties对应不一样的数据类型,及自定义的数据解析动做;
场景说明:获取数据集合后,能够获得每一个element的type,可是具体的properties的属性还须要进行再次处理,因此这儿如何拿到每一个element对应的具体类型,就是处理的关键。
在处理上述状况时,想到两种处理方式
1. 根据type建立一个Enum类,存储type对应的class,并初始化一个实例,再进行具体处理;
2. 根据type利用反射技术,从新建立一个对象,将其赋原始值后,再进行其具体类的指定处理动做;(本文只记录分析bug,不讲解反射)
当时没有想太多,采用的是第二种方式处理,利用反射(reflect)进行不一样类的针对性处理。
1. 遍历获取的抽象类的集合信息,得到element;
2. 判断其具体type,进行实例化新的对象(newInstance),得到该类,包含其父类全部的属性(注意此处);
3. 利用反射进行对新实例对象的赋值( field.set( newInstance,value ) 注意此处),以后进行具体的处理动做,如调用properties的解析函数...等;
上面的步骤在dev环境下,全部执行操做都是OK的,可是在集成测试阶段时,测试用例自动执行时,抛出【Method not found : $jacocoData】。
排查以后,发现是集成测试环境下,经过反射获取数据时,多出两个属性, $jacocoData ...(呃,那个属性忘了),这两个属性经过反射赋值时,就会抛出如上异常。
可是为何会出现上面的多余属性呢 ?
由于在集成测试阶段,测试用例执行的时候,maven集成了Jacoco来统计单元测试的代码覆盖率,而dev环境没有做相应的配置。
Jacoco 会利用编译器在编译期间加入 $jacocoData 成员变量,Jacoco使用 asm 实现字节码植入,是对指令级别上的字节码植入,从而能够定位到执行的代码行。
asm是什么?(CSDN)
ASM是一个java字节码操纵框架,它能被用来动态生成类或者加强既有类的功能。ASM 能够直接产生二进制 class 文件,也能够在类被加载入 Java 虚拟机以前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的全部元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,可以改变类行为,分析类信息,甚至可以根据用户要求生成新类。
ASM是一款操做class文件流的工具类,效率大大高于普通Java代码编译成class的方式。操做class流的方式其实就是经过手动操做jvm的指令集,来生成或修改class文件流。众所周知普通Java代码经过javac编译生成class文件后,再经过javap -v 便可查看反编译的相似汇编代码。而asm的实现方式就是完成这样的汇编代码。
如何解决该问题 ?(CSDN)
在反射遍历字段的时候,能够对字段进行判断看是不是复合字段,假如是复合字段就跳出,具体函数是:field.isSynthetic() 为true证实是复合字段,continue;
注:synthetic总的来讲,是由编译器引入的字段、方法、类或其余结构,主要用于JVM内部使用,为了遵循某些规范而做的一些小技巧从而绕过这些规范,有点做弊的感受,只不过是由编译器光明正大的,人为是没有权限的(但事实上有时候仍是能被利用到的)。
-_- 汗~~
查询以后,虽然也是只知其一;不知其二,可是程序运行时,抛的异常是能够先解决了,从新提交代码合并...............走你...........................
参考文档连接:
https://blog.csdn.net/shawn_ling/article/details/81205705
https://blog.csdn.net/samyang1/article/details/79853270
https://blog.csdn.net/kifgep/article/details/82757417
(愿你的每一行代码,都有让世界进步的力量 ------ fn)