专栏名称: 美团技术团队
10000+工程师,如何支撑中国领先的生活服务电子商务平台?数亿消费者、数百万商户、2000多个行业、几千亿交易额背后是哪些技术在支撑?这里是美团、大众点评、美团外卖、美团配送、美团优选等技术团队的对外窗口。
目录
相关文章推荐
字节跳动技术团队  ·  ByteBrain团队EuroSys25 ... ·  3 小时前  
InfoQ Pro  ·  充电计划 | 反卷“大”模型 ·  5 小时前  
InfoQ Pro  ·  Redis 之父:哪怕被喷我也得说,AI ... ·  5 小时前  
字节跳动技术团队  ·  基于LLM的AI应急:多模态信息智能化分析整 ... ·  昨天  
字节跳动技术团队  ·  稀土掘金 x Trae ... ·  2 天前  
51好读  ›  专栏  ›  美团技术团队

Robust 2.0:支持Android R8的升级版热修复框架

美团技术团队  · 公众号  · 架构  · 2023-05-18 19:58

正文

请到「今天看啥」查看全文


  1. 资源编译器(aapt/aapt2) :资源编译环节会生成一个 R.java 文件( 记录着资源 id,便于代码中引用 ),一般为了解决 R field 过多以及减少包大小,大型 Android 项目会在构建过程中会将资源 id 直接内联到调用处( 发生在 javac 和 proguard 之间 )。如果前后两次打包出现资源 id 不一致,会影响 diff 识别的结果。
  2. 代码编译器(javac) :Java 代码经过 javac 编译成字节码之后,除了有一些简单的优化( 如常量表达式折叠、条件编译 ),还有一些基础的脱糖(J ava 8 之前的语法特性 )操作会生成一些新的类/方法/指令,如匿名内部类会被编译成一个名为 OuterClass$1.class 的新类,以及命名为 access$200 之类的桥方法。如果改动涉及内部类、泛型,二次打包$后面的数字编号可能和线上包出现乱序。
  3. 代码优化器(ProGuard/R8) :目前主要使用第三方开源工具 ProGuard ( Google 推出 R8 计划取代 Proguard ),通过 30+ 可选优化项,对前面生成的 Java 字节码进一步压缩、优化、混淆,可以使得 Android 安装包更小、更加安全、运行效率更高:
  • 压缩 :通过静态分析并删除未被使用的 class/field/method,即源码中存在的 class/field/method,线上包中不一定存在。
  • 优化 :通过一系列优化算法或者模版,对字节码进行优化,使得构建产物更小、运行更高效/安全,优化手段有合并类/接口、内联短方法、裁剪方法参数、删除不可达分支、外联代码( R8 新增 )、删除无副作用代码( 如 Log.d() )、修改方法/变量可见性等等。优化后的字节码相比源码,可能出现 class/field/method 数量减少、field/method 访问修饰符发生变化、method 签名发生变化、code 指令变少,另外二次构建优化结果可能和线上包不一致。
  • 混淆 :通过将 class/field/method 的名称重命名为一个无意义的短字符,增加逆向难度,减少包大小。二次打包需要保证和线上包的混淆保持一致,不然补丁加载后因调用异常而发生崩溃。
  • 脱糖工具 图中未标出,旧版本使用三方插件 Lambda/Desugar,新版本中使用自带的 R8 ):由于低版本 Android 设备不支持 Java 8+ 语法特性,这一步需要将 Lambda 表达式、方法引用、默认和静态接口方法等高版本的语法特性转为低版本实现。其中 Lambda 表达式会被编译成一个内部类,会有类似(2)中的问题。
  • 至此,我们对本章开头提到的2个问题的产生原因有了一定认识,经过 Android 构建过程生成的字节码相比源码在 class/field/method/code 维度上有了“结构性”的变化,比如修复代码中调用的 class/field/method 在线上包中不存在( 被 shrink、被 merge、被 inline ),或者源码中可以访问、但在补丁中无法访问的 field/method( 修饰符被标记为 private )、method parameter 列表匹配不上( 之前没有被用到的 parameter 被裁剪了 )等等。
    Proguard 提供的这些优化项是可选的,一般情况下大型 Android 项目中会结合实际收益、稳定性以及构建耗时等多方因素综合考量后,会禁用一部分优化项,但并不是完全禁用。因此,二次打包时和线上包会产生一些差异,补丁制作准确性会受此影响。过去 Robust 补丁制作过程经常遇到此类问题,通过特殊字符检测、白名单等方式能够提升识别的准确性,但实现方案不够自动化。Robust 补丁制作流程如下:
    图2 Robust 补丁制作流程
    如果将 Android 项目的构建工具链( Android Gradle Plugin )升级到官方较新版本,上图中的 Proguard( Java字节码优化和 ) + Dex( Android 字节码生成 ) 两个环节将被合并成一个,并被替换成 R8:
    图3 两种构建流
    上述构建工具链的升级变化,给 Robust 补丁制作带来 2 个新的问题:
    1. 没有合适时机制作补丁。如果将基于 JAR 的改动识别方案,改成基于 DEX 或者 Smali,等同于更换补丁制作方案,前者需要基于 DEX 文件格式和指令,后者需要处理大量寄存器,更容易出错,兼容性和稳定性不够好。
    2. Proguard 可以禁用一部分优化选项,但是 R8 官方文档明确表示不支持禁用部分优化,相比之前会产生更多的差异,对改动识别造成干扰。

    3 解决思路

    | 3.1 整体方案介绍

    基于 R8 构建的补丁制作思路是将改动识别提到优化混淆之前,对比 Java 字节码,同时结合对线上 APK 结构化解析( class/field/method






    请到「今天看啥」查看全文