java代码热修复实现 java修复是什么意思

热修复实现原理(二)

直接在native层进行方法的结构体信息对换,从而实现完美的方法新旧替换,从而实现热修复功能。例如 AndFix 采用native hook的方式,以 Field 为切入点,直接使用dalvik_replaceMethod替换class中方法的实现。由于它并没有整体替换class, 而field在class中的相对地址在class加载时已确定,所以AndFix无法支持新增或者删除filed的情况(通过替换init与clinit只可以修改field的数值)。

成都创新互联自2013年创立以来,先为永德等服务建站,永德等地企业,进行企业商务咨询服务。为永德企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

在dalvik上的实现略有不同,是通过jni bridge来指向补丁的方法。

java 层的功能就是找到补丁文件,根据补丁中的注解找到将要替换的方法然后交给jni层去处理替换方法的操作

此处 主要在native层进行 ;一件事是判断当前环境是否支持热修复,一件事是初始化修复包安全校验的工作

就是从SharedPreferences读取以前存的版本和你传过来的版本进行比对,如果两者版本不一致就删除本地patch,否则调用initPatchs()这个方法

把扩展名为.apatch的文件加载到内存,初始化对应的Patch,并把刚初始化的Patch加入到我们之前看到的Patch集合mPatchs中

调用PatchManager. loadPatch;遍历mPatchs中每个patch的每个类,mPatchs就是上文介绍的存储patch的一个集合。根据补丁名找到对应的类,做为参数传给fix()

由于android 4.4 之后新增应用运行模式 此处分两种

在native层中会做art和dalvik虚拟机的区分处理工作,Java hook大致的逻辑都是一致的:

热修复Tinker(二)补丁包加载源码分析

p

前面一篇Tinker相关的文章已经介绍了Tinker热修复框架的使用与整个的修复流程,那么这一篇就要开启Tinker的源码解析之路了。

首先简单说一下Tinker的原理,Tinker其实也是类似multidex的dex方式,将目标dex插入到数组最前面,主要是通过对比原dex文件(存在bug)与现dex文件(bug已修复)生成差异包,生成的差异包作为补丁包下发给客户端,客户端做一系列校验之后,将下发的差异包与本应用的dex文件合并成成全量的dex文件,并进行opt优化,当再次启动APP时候则加载优化过的全量dex文件,将dex文件插入到DexPathList 中 dexElements的前面。

所以Tinker其实是两个流程,一个是加载补丁包,另外一个是加载dex文件,两个的加载流程相对较长,这里分开说明,这一篇呢,主要介绍加载补丁包的流程。

p

加载补丁包的方法如下

往下看发现调用了TinkerInstaller的onReceiveUpgradePatch方法

TinkerInstaller.java

这里调用了PatchListener的onPatchReceived方法

而PatchListener是一个接口,他的具体实现为SamplePatchListener方法,onPatchReceived在SamplePatchListener的父类DefaultPatchListener有实现,我们看下DefaultPatchListener中的onPatchReceived方法

如下

DefaultPatchListener.java

首先这个检测了一下这个插件是否可用,通过SamplePatchListener的patchCheck方法来检测

SamplePatchListener.java

这里对插件是否可用进行了判断,就不进行详细分析了

当插件可用时候returnCode为ERROR_PATCH_OK,当不可用则会log出来失败的errorcode

成功则调用

来启动TinkerPatchService这个IntentService,并且把插件的路径给传递到IntentService

TinkerPatchService通过onHandleIntent来接收传递过来的数据

TinkerPatchService.java

这里首先调用了PatchReporter的onPatchServiceStart方法,而PatchReporter的实现为SamplePatchReporter

SamplePatchReporter.java

这里主要看UpgradePatchRetry的onPatchServiceStart方法

UpgradePatchRetry.java

这里主要也做了一些验证,并且把文件复制一份到/data/data/tinker.sample.android/tinker_temp/路径下,然后把相关信息写入到配置文件中

在回到TinkerPatchService的onHandleIntent方法

主要看

这个方法的实现在UpgradePatch中

UpgradePatch.java

这里首先初始化相关数据与相关验证,再将补丁文件拷贝到目标目录中

路径为/data/data/tinker.sample.android/tinker/patch-xxxxxx/patch-xxxxxx.apk

接下来就是调用DexDiffPatchInternal,BsDiffPatchInternal,ResDiffPatchInternal这些类的方法进行dexDiff差分的计算相关

至于相关差分的计算,由于比较复杂,我暂时还没有深入去看,暂时埋个坑在这里,等后面找时间去填上这个坑

在回到TinkerPatchService的onHandleIntent方法

后面调用了PatchReporter的onPatchResult,这个方法主要删除了上面拷贝在/data/data/tinker.sample.android/tinker_temp/的文件

接下来启动了AbstractResultService,并把插件的路径传递过去了

AbstractResultService的实现在SampleResultService类里面,SampleResultService的onPatchResult删除了原始的插件文件。

到这里插件加载分析就基本结束了

p

插件加载分析结束了,但是却没有去分析dexDiff差分的计算,而这个dexDiff差分计算则是区分的Tinker与其他相同方案的热修复库,dexDiff是基于 Dex 的文件结构来下手,将产生变化的结构提取出来,产生的补丁非常小,而且在 diff 的过程中也处理了一些会造成补丁包很大的场景,所以等后面有时间将这一块补上,下一篇文章则是对dex文件加载进行源码分析了,peace~~~

热修复框架 - Tinker patch合成流程

经过TinkerInstaller.install 安装之后,Tinker相关初始化工作也都做好了,万事俱备等待手动执行合成patch包。

主动触发:

TinkerInstaller.java

DefaultPatchListener.java

TinkerPatchService.java

合成patch看upgradePatchProcessor.tryPatch

UpgradePatch.java

这里很简单,就是把你存放的patch差分包复制到/data/data/com.stan.tinkersdkdemo/tinker/patch-8b79c8cc/patch-8b79c8cc.apk中,然后分别执行dex、so 、resources与基准包的合成。

dex、so 、resources的差分与合成有时候的话后续再单独开篇分析下。

参考:

腾讯技术分享:热修复框架Tinker技术实践

演示如何使用腾讯的热修复框架-Tinker

项目地址

[图片上传失败...(image-8d08aa-1609383303209)]

[图片上传失败...(image-66d40c-1609383303209)]

由于原理与系统限制,Tinker有以下已知问题:

官方说明请 点击查看 .

这里我只想说几个比较关键的配置:

【注意】:AppKey和AppVersion都是用于 Tinker Platform 自定发布补丁包所需要的。如果你不使用Tinker Platform来管理你的热更新的话,可以随便设置。

以下是 tinkerpatch.gradle 的配置样例:

更多复杂的配置和高端自定义操作可参见 官方文档 。

以上就完成了Tinker的接入工作。

执行完成后,你会在你模块的 build-bakApk 下看到你打的apk包。

执行完成后,你会在你模块的 build-outputs-apk-tinkerPatch-release 下看到你需要的补丁包 patch_signed_7zip.apk 。

1.如果你使用的Java-8,你还需要在项目目录的 gradle.properties 文件中增加如下配置:

2.执行热更新后,需要重启程序或者锁屏才能生效!


文章标题:java代码热修复实现 java修复是什么意思
地址分享:http://scyanting.com/article/ddoppgo.html