Android tinker升级之路分析

2023-09-14 10:07:11

前言

目前app线上的tinker版本为 1.9.14.19,在最近的几个版本技术需求中,我们希望对tinker尝试进行升级,并对内部封装的tinker的包装sdk进行升级。升级过程中的一些热修流程和记录如下。

热修耗时时长分析

测试中,所有测试热修基本均可生效,但是对补丁合成生效时间有要求。耗时具体体现在:

  • tinker初始化
  • 下载补丁包
  • recover dex耗时(合并新dex文件)
  • parallel optimize dex(oat耗时)
  • 保存补丁信息(更新patch.info文件)

测试结果发现除了parallel optimize dex这一步,其他步骤耗时对比几乎不变,且耗时时长集中在parallel optimize dex这一环节。

升级前后数据对比

start to parallel optimize dex的时间对比(oat耗时)

机型耗时(ms) 线上包(版本:1.9.14.19)耗时(ms) 升级包(版本:1.9.14.25.2)
pixel 6a(Android 13)6333393393
180293400
185893386
vivo x80(Android 13)6336093399
284993457
小米10(android 12)6337593435
6333893368
华为mate40(android 12)448737506
500734520
小米8(Android 9)62056439
61486220
vivo x9plus(Android 7.1.2)78312 (热修不生效)78035 (热修不生效)
131601 (热修不生效)79475 (热修不生效)
小米5s Plus(Android 6.0.1)7661387717
6461762501

不同Android系统下tinker的oat流程总结

  • 华为荣耀系统tinker会通过registerDexModule方法注册dex,不会进行重试步骤(1.9.14.25.2版本重试10次,1.9.14.19版本重试3次);
  • android8.0 之下直接使用DexFile.loadDex加载补丁触发dex2oat;
  • android8 ~ android10,通过NewClassLoaderInjector.triggerDex2Oat进行dex2oat;
  • android10以后不再支持从应用进程调用dex2oat,仅接受系统生成的OAT文件(TinkerDexOptimizer.triggerPMDexOptOnDemand方法);
  • 重试的逻辑发生在TinkerDexOptimizer.triggerPMDexOptOnDemand方法中,DexFile.loadDex和进程内通过NewClassLoaderInjector.triggerDex2Oat进行dex2oat不会走该逻辑;该重试的逻辑会增加30s耗时。
  • 在老旧手机上步骤二recover dex耗时明显比新设备耗时长,这个和机型性能有关,升级的差异不在步骤二。

相关逻辑请参考版本tinker源码TinkerDexOptimizer.OptimizeWorker类的run方法。

附:patch合成生效时间分析

目前热修是肯定需要重启app的,但是在app拉取热修配置,下载patch包,然后重启app之前的这个时间节点上,tinker需要对patch包进行合成生效的操作,这部分会有耗时。

tinker核心代码:

TinkerPatchService 
         -  doApplyPatch(this, intent);

tinker issue上已经有人反馈了:

补丁从安装到提示安装成功需要多久,我就改了个Toast打印的字符串,需要大概100s,这正常吗?项目比较大 · Issue #1316 · Tencent/tinker · GitHub

最新版本补丁合成很慢(50s),不管 dex2oat 是否成功都会循环 N 次 · Issue #1670 · Tencent/tinker · GitHub

这个问题tinker *v1.9.14.25* 已经做了优化:

**1、**base包更新或有新 patch 合成成功后删除老 patch 的逻辑改为异步实现以降低启动耗时。

**2、**dexopt 触发重试次数缩减到 10 次,避免部分机型 apply patch 耗时太长。

但是从tinker目前的反馈来看,最新的几个版本会出现合成时间变长的case,目前还处于open状态。为了验证升级之后的tinker,在合成生效时间上与之前版本的差异,进行了线上tinker版本(1.9.14.19)的对照测试。测试见下。

image-20230914100146884

附:tinker版本升级内容记录

*v1.9.14.20*

  1. 修复了 OPPO & VIVO 部分机型加载 Tinker 时偶现的闪退问题。
  2. 增加了 Patch Dex 的 Dex2Oat 重试次数,以降低解释模式加载 Patch Dex 的概率。

*v1.9.14.21*

  1. 尝试修复极少数情况下因为 resources.apk 被意外修改导致 patch 后的资源找不到或失效的问题。

*v1.9.14.22*

  1. 修复了偶现的 Tinker ID 注入失败导致 Patch 包编译失败的问题。

*v1.9.14.23*

  1. 优化了判断 resources.apk 被意外修改导致资源 patch 失效的检测逻辑。
  2. 修复了连续两次 patch 中间更新了 base 包时可能导致最后一次 patch 失效的问题。
  3. 在 Patch 加载不成功时 installNativeLibraryABIWithoutTinkerInstalled() 方法不再注入 patch so 路径,避免 dex 和 so 不一致的问题。

*v1.9.14.23.1*

  1. 修复了 Android 4.4 设备上 getCurrentInstructionSet() 失败的问题

*v1.9.14.24*

  1. 修复了 R8 生成的特殊 DebugInfo 导致编译失败的问题。
  2. 增加 performSecondaryDexOpt 的重试次数,在重试失败后再尝试 registerDexModule,以尽量减小 Android R 上 odex 没有生成导致的性能开销。
  3. 在 performSecondaryDexOpt 重试无效前不在 OPPO、VIVO、XIAOMI、REDMI 的 Android S 或更新的系统上调 registerDexModule,规避已知的性能问题。
  4. 更新 *getProcessName* 的实现,在 *Android P* 及更新的系统上优先尝试 *Application.getProcessName()* 方法。

*v1.9.14.25*

  1. 增加了32位 Android N 及更旧的系统上使用解释模式触发 dexopt 的开关以帮助减少 32位上 VmSize 的开销。
  2. 修复部分机型上资源有变更时 patch 失败的问题。
  3. base包更新或有新 patch 合成成功后删除老 patch 的逻辑改为异步实现以降低启动耗时。
  4. dexopt 触发重试次数缩减到 10 次,避免部分机型 apply patch 耗时太长。

*v1.9.14.25.1*

  1. 修复了 anim 资源新增、修改检测逻辑,在 anim 资源发生新增或修改时会中断编译。
  2. 获取当前进程名的方法在 api level >= 18 的机器上优先使用反射 ActivityThread 的方式实现,若失败则改用 BufferedReader 读 proc 的方式实现。

*v1.9.14.25.2*

  1. 修复了部分机型上无法加载新增资源及修改资源不生效的问题(flutter加载asset时必现)。
  2. 新增了异步触发patched dex的dex2oat并且不等待其执行完毕的patch合成接口,以满足开启时长较短的App紧急修复问题时需要Patch能快速生效的需求。

参考

Android 热修复Tinker源码分析(二)补丁包的合成 - 掘金

更多推荐

【Linux】基础IO,软硬链接,动静态库

1.认识IO什么是IOI/O简单来说对应的就是两个单词Input和Output,指的是计算机系统与外部环境(通常是硬件设备或其他计算机系统)之间的数据交换过程I/O可以分为两种主要类型:输入(Input):输入是指计算机系统接收来自外部环境的数据或信息的过程。例如,当用户在键盘上输入文本时,这些输入字符被视为输入操作。

9.21号作业

实现把注册的信息导入数据库中second.h#ifndefSECOND_H#defineSECOND_H#include<QWidget>#include<QDebug>namespaceUi{classSecond;}classSecond:publicQWidget{Q_OBJECTpublic:voidnewsl

IT运维:使用数据分析平台监控Windows Eventlog

TIPS:本文鸿鹄版本:2.10.0及以上版本概述本文基于《IT运维:利用鸿鹄采集Windowseventlog数据》(以下简称原文)文章进行了细化与延伸。主要包括细化了安装步骤,增加了仪表板。鸿鹄端配置创建数据集与数据源类型登录鸿鹄提前创建数据集和数据类型,我这里创建的是winlog数据集,下文《安装vector》里

埃文科技受邀出席“安全堤坝”技术论坛

2023年9月11日,2023年国家网络安全宣传周河南省活动开幕式暨河南省网络文明大会在开封博物馆开幕。由CCFYOCSEF郑州举办的“聚焦数据交易监管技术,筑牢数据交易‘安全堤坝’”技术论坛在开封市博物馆二楼会议厅举行。埃文科技总经理王永博士与副总经理武可嘉受邀出席,发表演讲并参与思辨讨论。埃文科技王永博士从“数据流

数据分析思维-分析方法(基础)

数据分析的基础方法概念理解,其关键在于在业务中锻炼数据分析思维。(将以下基础方法带有好奇心的应用在生活中练习数据分析思维)例如:经典的啤酒与尿布(分析一个爸爸去超市买东西的行为,将尿布和啤酒放在一起)例如:分析夜市上100家店那些营业高、利润经营类型等等主要是养成数据分析的思维,可应用工作、生活日常的方方面面。1.象限

Java学习笔记39——网络编程03

TCP通信程序TCP通信程序TCP通信原理TCP发送数据的步骤TCP接收数据的步骤TCP通讯程序练习练习1练习2练习3练习4练习5练习6TCP通信程序TCP通信原理TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通

URL与URI小结

文章目录一、URL是什么?URL的一般形式:二、分类三、URI总结一、URL是什么?每条由Web服务器返回的内容都是和它管理的某个文件相关联的,这些文件中的每一个都有一个唯一的名字,叫做URL(通用资源定位符),是互联网上一种资源的地址。例如:http://www.google.com:80/index.htmlURL

实训笔记——Spark计算框架

实训笔记——Spark计算框架Spark计算框架一、Spark的概述二、Spark的特点三、Spark的安装部署(安装部署Spark的ClusterManager-资源调度管理器的)3.1本地安装--无资源管理器3.2Spark的自带独立调度器Standalone3.2.1主从架构的软件3.2.2Master/work

第26章_瑞萨MCU零基础入门系列教程之独立看门狗定时器-IWDT

本教程基于韦东山百问网出的DShanMCU-RA6M5开发板进行编写,需要的同学可以在这里获取:https://item.taobao.com/item.htm?id=728461040949配套资料获取:https://renesas-docs.100ask.net瑞萨MCU零基础入门系列教程汇总:https://b

在springboot下将mybatis升级为mybatis-plus

在springboot下将mybatis升级为mybatis-plus1.整体描述2.具体步骤2.1更新pom引用2.2更新yml配置2.3更新config配置2.4BaseEntity修改3.程序启动4.总结1.整体描述之前项目工程用的是mybatis,现在需要将其替换为mybatis-plus,mybatis-pl

电商项目高级篇-01 elasticsearch

电商项目高级篇-01elasticsearch1、linux下安装elasticsearch和可视化工具2、docker设置虚拟机开机启动和容器开机启动3、elasticsearch的curd3.1、新增、更新3.2、查询1、linux下安装elasticsearch和可视化工具将安装好jdk1.8和tomcat的ce

热文推荐