一个混淆后报NullPointerException的问题

最近的项目中需要集成一些扫描枪厂家的第三方SDK,前面都还算顺利,今天集成的这一家,开始也没有问题,但是开启了混淆后,会报NullPointerException,提示sdk包中的类找不到.问题比较少见,比较意外,多方尝试后才得到解决.背后的原理也还没有理清,记录备查.

问题表现

在一个有扫描功能的抽象类中,实例化一个sdk中的类,非常简单.

scanManager = ScanManager()

混淆过后,该行代码报NullPointerException.显然是ScanManager()报的.在這里断点,进来以后一执行ScanManager()就报错了.关闭混淆的情况下,则可以成功构造出实例.

尝试解决

  1. 首先当然是添加这个jar包的,混淆保持策略,整个包保存,这个sdk的包名,不是很常见,用的是安卓系统类型的包名:android.device.ScanManager,android.device.DeviceManager这种.在:app的proguard-rules.pro中添加:

    -keep class android.device.** { *; }
    

    keep整个包不被混淆,跑起来问题还是一样.

  2. 怀疑是混淆策略没有起效,这个包内的类还是被混淆了,手动拖入混淆后的apk到as中,查看dex结构.发现:

    在这里插入图片描述

    目标包并没有被混淆,

    在这里插入图片描述

    我自己的类已经混淆成功了.同时尝试keep 调用ScanManager的类的所有代码也无效.问题依旧.

  3. 还有很多其他的尝试,keep ScanManager到mainDex等,最后都没有效果.

解决

虽然最终也没有搞清楚是什么原因引起的,但是经过上面的分析,我确定混淆规则确实是起效了的,ScanManager并没有被混淆,可能是因为比较特殊的包名,在读取这个class的时候,classLoader没有找到,或则不被支持等问题.这个也是臆测,要是class没有找到难道不应该报ClassNotFoundException么?反正最后也没能搞清楚原因.但是说到了classLoader就想起了Tinker热修复实现原理中,让classLoader提前找到要修复的类返回的操作.那么這里是不是因为classLoader没有找到ScanManager或者是找的过程中出现了什么问题呢?修改ScanManager初始化代码如下:

scanManager = Class.forName("android.device.ScanManager",true,classLoader).newInstance() as ScanManager?

其实也没有深入到classLoader的具体使用,只是简单的用反射创建新实例.相当意外的.问题得到了解决,开启混淆后,這里也不会报错了,感觉还是类加载过程中出现的问题.具体是为什么呢?//todo 2019-7-29 16:25:07

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值