请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

自研代码实现热修复问题

1.代码执行报错:

Unable to instantiate application com.imooc.hotfix.App: java.lang.RuntimeException: kotlin.TypeCastException: null cannot be cast to non-null type java.lang.Class<kotlin.Any>

断点调试的时候发现是在执行下面这段代码报的错:
// DexPathList 类里面 makeDexElements 方法
val makeDexElements = ReflectUtil.findMethod(
dexPathList,
“makeDexElements”,
List::class.java,
File::class.java,
List::class.java,
ClassLoader::class.java
)
是反射获取方法不被允许吗?

2. 5.0及其以上的系统本课程介绍的热修复代码应该无效,对吗?

之前老师说5.0及其以上的系统(art虚拟机)会在“安装包安装的时候”将dex文件合并编译成机器码,上面的热修复实现是在程序运行的时候执行的,基于这个逻辑是应该无效吗?

正在回答 回答被采纳积分+3

1回答

allenfeng 2021-01-21 11:43:13
  1. 建议根据具体的Crash堆栈确认具体报错的代码行号。根据你的描述可能是上一步获取到的dexPathList为null,可以打印确认下。

  2. ART虚拟机中,被提前编译的,只有安装包内根目录下的的 classes.dex、classes2.dex ... 这些dex,这是APK安装过程中执行的。我们自己生成的补丁dex不在安装包内,是安装后,才被推送到手机内存中,不会被系统提前编译。当应用启动后,我们会手动将自己的补丁dex插入到PathClassLoader内dexElements数组的最前方,后续查找类会优先命中我们的补丁类,从而达到热修复生效的效果。因此,5.0及其以上的系统中,我们的机制也是可以生效的。


0 回复 有任何疑惑可以回复我~
  • 提问者 慕勒4168567 #1
    代码执行报错的问题:
    老师给的仓库代码HotFixUtil.kt 这个类中的第45行和第62行是不是应该删掉,多传了ClassLoader参数导致反射调用对应的方法出错了
    回复 有任何疑惑可以回复我~ 2021-01-21 14:48:24
  • allenfeng 回复 提问者 慕勒4168567 #2
    热修复的核心操作需要反射调用一些隐藏的API,而这些API在不同版本的系统上,是可能不一致的。
    
    例如makeDexElements这个方法,在不同版本的参数列表就不一样:
    
    【Android 11】 https://cs.android.com/android/platform/superproject/+/android-11.0.0_r1:libcore/dalvik/src/main/java/dalvik/system/DexPathList.java;drc=android-11.0.0_r1;l=363
    
    【Android 5.1.1】
    https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:libcore/dalvik/src/main/java/dalvik/system/DexPathList.java;l=203
    
    
    咱们课程中演示的代码是在 最新的Android 11 的系统上可以正常工作的。如果是其他版本的系统,需要根据对应版本的源码,调整反射代码去兼容(可以通过版本号增加if-else逻辑),才能成功运行。
    
    一般成熟的热修复框架,都是需要针对不同版本的系统去进行兼容的。
    回复 有任何疑惑可以回复我~ 2021-01-21 15:14:59
  • 提问者 慕勒4168567 回复 allenfeng #3
    明白了,3q!查源码的网站挺好,收藏。
    回复 有任何疑惑可以回复我~ 2021-01-21 15:44:54
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信