Android热修复框架HotFix分析拓展

本文有两个目的:

  1.是分析一下hotfix的实现,

  2.换一种实现防止类打上CLASS_ISPREVERIFIED标识

首先分析一下hitfix的实现:

hotfix工程结构

  1.app是demo的工程

2.builSrc是操作class文件的封装类,做的操作是向class的构造函数中插入了这么一段代码

  编辑class文件使用的工具是javassist。

3.hackdex工程是防止类呗打上impressive标识的类。

4.hotfixlib是动态加载工具的封装

动态修复有两个关键的点:

1.防止类被打上CLASS_ISPREVERIFIED

2.动态加载需要修复的类

1.防止类被打上CLASS_ISPREVERIFIED

防止类被打上CLASS_ISPREVERIFIED的关键是:可能出现bug需要热修复的类必须引用一个app外部的类

hotfix的做法是使用腾讯公开的方法,对应的类是PatchClass,使用javassist工具在app打包之前,把可能需要修复的类的class文件进行修改,每个类的构造中都插入了这句话。

引用的类AntilazyLoader以jar包的方式动态加载,放在了asset文件夹中,程序运行时把jar拷贝到sd卡中,这个jar是用dx命令处理过的jar文件,命令如下(loader是要处理的jar,loader_dex.jar是处理后的jar):

   dx --dex --output=loader_dex.jar loader.jar

工程的gradle文件中需要做的是:

这是一个task,gradle编译工程实际上就是由多个task组成,按照一定的顺序执行task。例如先编译java代码,打包代码为jar,打包成app,这三个操作可以写作3个task,按照顺序执行就生成了一个app。当然实际的过程不是这样,这里只是一个比喻。

然后是:

在最下面的红色方框中有一句话variant.dex.dependsOn << processWithJavassist //在执行dx命令之前将代码打入到class中

这里的variant.dex是应该是在app打包过程中打包处理class文件的任务。dependsOn表示依赖与某个任务,只有一排的任务执行完了它才能执行。后面的processWithJavassist就是前面提到的task,这个task的目的就是向class文件中的狗仔函数插入代码。这句话的意思是处理class文件之前(比如打包成dex文件)先向每个class文件的构造中插入代码,然后再打包。这样每个class都引用一个app外部的类,防止打上CLASS_ISPREVERIFIED标识。

2.动态加载需要修复的类

动态加载的核心原理就是下面两张图,是BaseDexClassLoader的源码(图非原创,源自网络,本人没找到这两个类的源码。。。),BaseDexClassLoader中的DexPathList的dexElements属性,存储的是所有的类。

把修复好bug的类合并到app的classloader的dexElements中,就可以用修复好bug的类替换原有的类了。

hotfix加载类的源码是:

str是包涵修复好bug类的jar包路径,str2是需要加载的类名。本质上的操作时实例化一个classloader,加载补丁包,将dexElenemts合并到app的classloader的dexElements数组中,并且放到最前面。(其实最后一句pathClassLoader.loaderClass(str2)不要也可以)

改进:hotfix框架为了实现类中引用app以外的类,通过使用javassist向字节码中插入代码的方式实现。这种方式要引用javassist包并且需要对javassist有一定的功底。另外还需要对gradle构建android项目有比较深入的了解。

笔者所说的改进是:要实现引用app外部的类还有一个方法,只需要把相关的类打包成jar,但是编译app时不将jar打包进app即可。

这里的改进涉及到插件化开发的一些知识,先给大家讲解一下基本的设计思路,深入了解需要自行学习,这里不做深入讲解。

对插件化开发或者更换app主题(Theme)了解的童鞋们可能知道,当我们想动态更换app的主题时,

首先,一般会有一个公共接口Interface库,里面定义了基本的主题(Theme)内容,比如:标题字体颜色、背景色等等,我们的app要引用这个Interface库。

第二,Interface导出jar,供主题(Theme)工程使用,重点来了,使用Interface接口的jar包,但是打包主题(Theme)的时候,不管你是打包成app还是其它的包(例如arr,貌似可以打包资源文件)不要把Interface的jar包打包进去,否则会报错,错误类型是:

Class ref in pre-verified class resolved to unexpected implementation

和热修复时类被打上了CLASS_ISPREVERIFIED标识报的错误一样。

当时研究插件化开发的时候还不是很理解这个错误的根本所在,后来研究热修复的时候想起来了这一点,前后一对比发现两者的错误类型是一样的,就想是不是可以不借助javassist和gradle中修改variant.dex.dependsOn
<< processWithJavassist
进行防止类被打上CLASS_ISPREVERIFIED标识。

看到这里有的童鞋可能猜到接下来怎么做了。既然借助javassist和修改gradle编译过程是为了实现引用app外部类,那为何不打包一个jar1,所有可能被热修复的类都引用这个类,但是打包app的时候不要把这个jar1文件打入app中不就可以了么。jar2包放在asset文件夹中app运行的时候考到sd卡中,动态加载jar2就可以了。

这里又一个需要注意的点,对于初步接触热修复的童鞋有一个容易犯的错误,上面我提到了两个jar包jar1和jar2,他们有什么区别和联系呢?我们开发的时候引用的jar包都是正常的jar包,但是android的classloader加载的jar包必须是dex命令处理过的,就是上面我提到的dx命令:

dx --dex --output=loader_dex.jar loader.jar

jar1是正常情况导出的包,我们在项目中引用的包。jar2是jar1用dx命令处理过的,放在asset中,app运行时考到sd卡中,动态加载。jar1和jar2包含的类是完全一样的,区别就是一个没有用dx处理过,一个用dx命令处理过。

至于如何实现打包时不把jar打包进app,我简单说一下,网上都可以搜到。

1.eclipse jar包不要放到libs文目录下,libs目录下都是会被打入app中的,你可以随便见一个目录,jar包考进去,右键jar包,build path ---> add to build path即可,这样这个jar就不会被打入app中。

2.studio 依赖某个jar包一般是compile fileTree(dir: ‘libs‘, include: [‘*.jar‘]),表示编译libs下所有的jar文件。我们需要建一个新目录,把jar考进去,然后provided ‘需要引用的jar‘,正常的compile是表示把引用的东西都要打包进app,provided表示只引用不打包。有的童鞋可能想为啥还要打包jar1,直接provided工程不就的了么,只需要一个jar2就够了。因为provided只能引用jar包,不能引用工程。。。

以上就是所有内容,亲测没问题,欢迎指正。

时间: 2024-10-24 22:57:06

Android热修复框架HotFix分析拓展的相关文章

Android热修复框架汇总整理(Hotfix)

??Android平台出现了一些优秀的热更新方案,主要可以分为两类:一类是基于multidex的热更新框架,包括Nuwa.Tinker等:另一类就是native hook方案,如阿里开源的Andfix和Dexposed. 基于native hook的方案 ??需要针对dalvik虚拟机和art虚拟机做适配,需要考虑指令集的兼容问题,需要native代码支持,兼容性上会有一定的影响: 基于Multidex的方案 ??需要反射更改DexElements,改变Dex的加载顺序,这使得patch需要在下

Android热修复框架AndFix原理解析及使用

一.前言 最近腾讯弄出一个Tinker热修复框架,那么本文先不介绍这个框架,先来介绍一下阿里的一个热修复框架AndFix,这个框架出来已经很长时间了,但是看网上没有太多非常详细的讲解,这里就来做一次分析.正好项目中要使用到.首先这个框架是开源的:https://github.com/alibaba/AndFix 其实在最早的时候我已经分析了阿里的另外一个热修复框架:Dexposed框架,还不了解的同学可以点击这里查看:Dexposed框架原理解析以及使用 当时介绍这个框架的时候发现他的实现原理很

一款超级简单易用的Android热修复框架 WandFix 使用详解

WandFix是一个基于java ClassLoader实现的热修复框架. 效果展示: 优点: 类似于黄油刀可以直接对成员变量添加@InjectObject("com.example.motordex.AppParsenterImpl2")注解,来绑定热修复包中的实现类. 无需关闭应用即可使修复包生效. 与mvp模式搭配使用效果最佳. 可以自己定义需要热修复的类. 可以自己配置dex加密算法,保护dex文件的安全. 可以通过注解单独设置某个对象是否禁用双亲委托. 使用 使用方法: gi

Android热修复(HotFix)实战

线上的BUG一直是程序员头疼的问题.有时候仅仅是因为几行的代码,就能让你的用户损失严重.谷歌在Android Studio 加入了Insttan Run 机制.通过Apk动态加载的技术实现了应用非安装而进行代码层的改变.之后QQ空间团队的补丁开始了热更新的浪潮.用户不需要通过手动操作,进行App的版本更新,极大的保障了用户对于产品的粘合度,对于开发者而言能使用到这项技术当然再好不过,市面上的热更新,热修复他们的叫称不同,功能相同只是支持的范围有所差别.目前可用的开放平台有腾讯的Tinker以及H

Android热修复学习之旅——HotFix完全解析

在上一篇博客Android热修复学习之旅开篇--热修复概述中,简单介绍了各个热修复框架的原理,本篇博客我将详细分析QQ空间热修复方案. Android dex分包原理介绍 QQ空间热修复方案基于Android dex分包基础之上,简单概述android dex分包的原理就是:就是把多个dex文件塞入到app的classloader之中,但是android dex拆包方案中的类是没有重复的,如果classes.dex和classes1.dex中有重复的类,当classes.dex和classes1

Android热修复:Andfix和Hotfix,两种方案的比较与实现

Andfix和hotfix是两种android热修复框架. android的热修复技术我看的最早的应该是QQ空间团队的解决方案,后来真正需要了,才仔细调查,现在的方案中,阿里有两种Dexposed和Andfix框架,由于前一种不支持5.0以上android系统,所以阿里系的方案我们就看Andfix就好.Hotfix框架算是对上文提到的QQ空间团队理论实现.本文旨在写实现方案,捎带原理. Andfix 引入 框架官网:https://github.com/alibaba/AndFix 介绍是用英文

Android热修复之微信Tinker使用初探

文章地址:Android热修复之微信Tinker使用初探 前几天,万众期待的微信团队的Android热修复框架tinker终于在GitHub上开源了. 地址:https://github.com/Tencent/tinker 官方介绍:https://my.oschina.net/shwenzhang/blog/751618 接入指南:https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%9

Android 热修复方案分析

绝大部分的APP项目其实都需要一个动态化方案,来应对线上紧急bug修复发新版本的高成本.之前有利用加壳,分拆两个dex结合DexClassLoader实现了一套全量更新的热更方案.实现原理在Android 基于Proxy/Delegate 实现bug热修复这篇博客中有分解.因为这套方案是在Java端实现,并且是全量更新所以兼容性较好,成功率较高.但是在线上跑了几个月之后就碰到了瓶颈,因为随着业务的增长分拆过之后的dex文件方法数也超过65535个,更换拆包方案的话维护成本太高.同时由于没有做差异

Android中热修复框架Robust原理解析+并将框架代码从&quot;闭源&quot;变成&quot;开源&quot;(下篇)

一.回顾框架原理 本篇继续来看热修复框架Robust原理,在之前的一篇文章中已经详细讲解了:Robust框架原理,因为这个框架不是开源的,所以通过官方给出的原理介绍,咋们自己模拟了案例和框架逻辑的简单实践.最后在通过反编译美团app进行验证咋们的逻辑实现是否大致不差.最终确定实践的逻辑大同小异.但是在上一篇文章末尾多次强调了,这个框架吸引我研究的不是他热修复技术,而是他有一个技术点,就是如何在编译期给每个类每个方法都加上修复功能代码,对于上层开发代码是透明的.因为从之前案例可以看到,如果方法没有