UDN-企业互联网技术人气社区

板块导航

浏览  : 1768
回复  : 0

[讨论交流] JAVA代码覆盖率工具JaCoCo-踩坑篇

[复制链接]
舞操的头像 楼主
发表于 2016-8-30 18:24:58 | 显示全部楼层 |阅读模式
  一、覆盖率踩过的坑

  在项目中使用JaCoCo覆盖率的时候,也遇到过各种奇葩的问题,在这里列出来分享下,问题和实际的项目关系密切,希望对有遇到过相似问题的童鞋有所启发。

  1.1 覆盖率包在部分手机6.0上安装失败

  事情起因:在测试新功能时,用打的覆盖率包,外包反馈部分手机6.0上安装不了。

  问题重现:试了在自己的手机,华为mate8的6.0系统上安装正常,属于部分机型问题。

  将问题小米手机借来后,发现用豌豆荚或者应用宝确实安装失败,提示“该应用签名有问题,无法安装。”通过adb install安装,提示INSTALL_PARSE_FAILED_NO_CERTIFICATES

  怀疑是部分厂商对签名的校验级别比较高。

  问题排解:

  (1) 网上有种说法,jdk1.7以后变更了默认的加密算法,而签名程序没有,所以需要在签名时用参数指定。

  具体方法:在签名命令后加入-digestalg SHA1 -sigalg MD5withRSA

  会不会这种情况导致:查了应用宝的打包脚本,签名部分已经增加。

1.webp.jpg


  此种情况排除

  (2) 会不会签名文件有问题?

  重新排查了打包过程的签名,密钥和口令都和RDM打包一样,对ANDROIDR.RSA、ANDROIDR.SF、MANIFEST.MF,清除掉签名,重新进行签名,问题仍然存在。

  此种情况排除

  (3) JaCoCo的jar包重新签名

  和RDM打包,也就增加了JaCoCo部分,会不会是JaCoCo的两个jar包jacocoagent.jar和jacocoagent.jar出的问题?

  这两个jar包已经是签名过的,会不会需要用应用宝的签名进行重新签?

  使用jarsigner重新对这两个jar包用应用宝的密钥进行签名,打包安装,问题仍然存在。

  此种情况排除

  到这里,网上的各种方法基本都试过了,没任何效果,问题纠结在这里了。

  静下心来,网上的方法没任何效果,还是回到项目中,重新一步一步的对比RDM打包和覆盖率打包的区别,逐步排查吧。

  (4) RDM打包和覆盖率打包逐一对比

  ....(这里省略一万字,都是排查)

  签名部分的日志对比:

  我们还是回到打包签名的target:sign_obfuscated

  逐行对比RDM和我们覆盖率打包的日志:

  发现了一个不同的点:

  RDM的:

2.webp.jpg


  我们打包的:

3.webp.jpg


  大家看出差别了没(红色部分)

  红色部分为jacocoagent.jar包里的非class文件,signer对这两个文件也进行了签名。

  到这里都不是问题。

  问题还是业务脚本本身(┬_┬哭~)

4.webp.jpg


  签名后做compress和zipalign,据说是极限压缩,减少包的大小。

  Compress会调用compress_yingyongbao.sh脚本,这里列出了所有要压缩的文件

5.webp.jpg


  看到没,看到没,它重新按这里的文件列表压缩打包,丢掉了上面JaCoCo里面的两个文件

  应用在打包后,签名文件是存在JaCoCo这两个文件的,但打包后找不到这两个文件,因此安装时有的手机提示签名有问题。

  解决方法:

  JaCoCo这两个文件,一个是属性文件,一个是生成xml的dtd文件,对我们生成覆盖率没多大作用,我们把这两个从jar包里删除,在重新打包,这两个文件不存在了,也就不用签名了,问题就解决了。

  1.2 覆盖率包在部分4.X版本手机上生成ec文件失败

  事情起因:在测试新功能时,用打的覆盖率包,外包反馈部分4.X手机生成不了ec文件

  问题重现:试了在自己的手机,华为mate8的6.0系统上生成正常,属于部分机型问题。

  将问题手机借来后,生成ec文件提示失败。

  问题排解:

  查看logcat日志:

6.webp.jpg


  还有一段:

  反射RT类的getAgent() 方法是提示

7.webp.jpg


  (1) 反射在其他手机是正常的,按道理不应该在部分问题手机会失败,但也做一下排查

  报错的代码行:

8.webp.jpg


  网上有说InvocationTargetException问题可能是没有设置可见就访问私有

  先看看RT的这个方法

9.webp.jpg

  在看看Agent类的这个方法:

a.webp.jpg


  尝试把私有字段可见,在去调用

b.webp.jpg


  结果问题仍然存在,此种情况排除

  (2) 那我们就回到第一个错误, Class resolved by unexpected DEX

  Agent出了两个地址。

  我们在回过头来看应用宝的打包脚本,看看dex干了什么。

c.webp.jpg
d.webp.jpg


  调用dex,输入classes,输出dex,下面对excludes里面的jar进行了排除

  调用dex_sub,输入subclasses,输出second_dex,下面对excludes里面的jar进行了排除

  回过头来在看看我们的插桩脚本,对dex、dex_sub这块只改了classes为classes_instr(用插桩后的打dex)

  应用宝这个分包的逻辑,会分别打两个dex。

  问题就找到了,因为没有改excludes部分,jacocoagent.jar是放在应用宝libs目录下的,默认dex和dex_sub都把jacocoagent.jar打了进去,运行时就会出现新的dex想要替换之前校验过的dex,也就出现agent有两个地址的缘故。

  解决方法:

  覆盖率打包的脚本,对dex_sub的excludes中加入jacocoagent.jar,这样两次dex只打一次jacocoagent.jar。

  重新打包,ec文件正常生成。

  1.3 覆盖率报告生成后看不到源码覆盖情况

  源码和类文件都正确指定了,为什么生成的报告看不到源码覆盖?

  解决方法:

  (1) 编译的时候debug="true" 这个一定要设置,比如

e.webp.jpg


  (2) 如果1没有错误,那就要看看你的源码和class文件路径指定正确没,JaCoCo是按照包名去搜索的,这个一定要确定好,很多项目会自建代码目录的。

  二、覆盖率一些需要注意的地方

  由于Android不能通过JVM停止后自动dump覆盖率数据,因此当Android应用进程不存在或停止的时候,覆盖率数据不会生成。

  也就有了如下需要注意的地方

  (1) 没有启动应用进程,生成覆盖率数据会失败。

  (2) 覆盖率生成工具进程杀不杀掉,不影响覆盖率生成结果。

  (3) 测试过程中,杀掉应用进程,内存中的覆盖率数据会丢失。

  (4) 覆盖率数据是可以追加记录的,但最好在杀掉应用进程前先备份。

  建议养成良好的操作习惯,定期生成覆盖率文件。

  如果有杀掉应用进程的需求操作,请在操作前生成一次,这样之前的数据就有所保留了。

  一次测试前,一定要保证先清理掉以前覆盖率的数据,否则以现有追加文件的方式的形式,会导致旧新的覆盖率柔和在一起,有可能merge时候会失败。

原文作者:刘洋  来源:开发者头条

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部