彩神大发快三_神彩大发快三官方

Android热修复技术总结

时间:2020-01-23 20:10:31 出处:彩神大发快三_神彩大发快三官方

不过微信的方案仍然会有如下大问题:

clinit法律土辦法 会在类加载阶段的类初始化时调用,clinit中静态field和静态代码块的一直出现顺序而且二者在源码中一直出现的顺序。可能性类可能性加载过了,什么都就算修复了clinit法律土辦法 而且会生效了。

dvmResolveClass->dvmLinkClass->dvmInitClass,而且执行clinit法律土辦法

以下情形会去加载一一六个多类

1.new 一一六个多类的对象时new instance

2.调用类的静态法律土辦法 (invoke static)

3.获取类的静态域的值(sget)

针对现在市面上比较流行的热修复方案,这里选则Sophix、QQ超级补丁和Tinker进行简单的介绍。前面说过,同类于qq空间和微信的实现法律土辦法 都时需重新启动不能修复bug,而阿里的Sophix采用的是非浸入式的法律土辦法 不时需冷启动。

父类是泛型类有setNumber(T value),子类想override setNumber(Number value)。然而实际父类的法律土辦法 实际是setNumber(Object value),子类想重写却变成了重载,这就一直出现了类型擦除和多态之间的冲突。然而编译器自动帮我们歌词 歌词 我们歌词 歌词 合成了Bridge法律土辦法 实现了重载,在子类中生成了相同签名bridge法律土辦法 ,外部实际调用子类的重写法律土辦法 。

嘴笨 可不时需很大地节省空间,但可能性对dex内容的比较粒度过细,实现较为多样化,性能消耗比较严重。实际上,dex的大小占整个apk的比例是比较低的,一一六个多app中间的dex文件大小删改都是随后 是主要要素,而占空间大的主要还是资源文件。而且,Tinker方案的时光图片 代价转换的性价比不高。

微信的热修复的流程如图所示:

AndFix:由补丁类的classLoader加载补丁类,在native层针对不同Android架构中的不同的ArtMethod型态调用对应的replaceMethod法律土辦法 按照定义好的ArtMethod型态一一替换法律土辦法 的所有信息如所属类、访问权限、代码内存地址等。

稳定性较差,会受到国内ROM厂商对ArtMethod型态更改的影响,什么都这正是AndFix不支持什么都机型的因为。

Java泛型删改有编译器实现,由编译器执行类型检查和类型推断,生成非泛型字节码,称之为擦除。

如此泛型前一天太满再再实现类泛型,利用所有类的父类时Object进行强转,这删改依赖多多多线程 员的自主性,很容易一直出现ClassCastException。泛型的一直出现出理 了类型检查和类型推断的大问题。

新增/减少匿名外部类对热部署是无解的,可能性补丁修复工具拿到的是class文件,无法区别DexFileDemo&1和DexFileDemo&2,会因为类的顺序乱套。可能性匿名外部类插入到末尾则是允许。

嘴笨 ,dex比较的最佳粒度,应该是在类的维度。它既不像法律土辦法 和指令维度那样的细微,而且像bsbiff比较那般的粗糙。在类的维度,可不时需达到时间和空间平衡的最佳效果。基于同类准则,我们歌词 歌词 我们歌词 歌词 另辟蹊径,实现了同类删改不同的全量dex替换方案。

外部类可能性有外部类把所有的field/method的private访问权限改成proteced可能性public外部类将所有的field/method的private访问权限改成proteced可能性public。

新增lamada表达式会因为外部类新增一一六个多辅助法律土辦法 。修改的lamda表达式逻辑引用了外部变量,会因为辅助类持有了外部对象,会新增同类外部对象的变量。也是会因为热修复失败。

可能性字段居于了增加和减少,和法律土辦法 变化的情形一样,所有字段的索引删改都是居于变化。而且更严重的大问题是,可能性在多多多线程 运行中间某个类一直增加了一一六个多字段,如此对于一一六个多可能性产生的同类类的实例,它们还是一一六个多的型态,这是无法改变的。而新法律土辦法 使用到哪几种老的实例对象时,访问新增字段就会产生不可预期的结果。

底层替换方案是在可能性加载了的类中直接替换掉原有法律土辦法 ,是在一一六个多类的基础上进行修改的。因而无法实现对与原有类进行法律土辦法 和字段的增减,可能性一一六个多将破坏原有类的型态。

热部署不支持field/method增加和删除和 clinit法律土辦法 的修改,静态field的初始化和静态代码块会被编译在编译器合成的法律土辦法 clinit中,非静态字段的初始化会被编译在编译器生成的init无参构造函数中,

微信针对QQ空间超级补丁技术的欠缺提出了一一六个多提供DEX差量包,整体替换DEX的方案。主要的原理是与QQ空间超级补丁技术基本相同,区别在于不再将patch.dex增加到elements数组中,而且差量的法律土辦法 给出patch.dex,而且将patch.dex与应用的classes.dex合并,而且整体替换掉旧的DEX文件,以达到修复的目的。其原理图如下:

在Android热修复的过程中,不仅时需对错误的代码进行修复,还时需对资源文件进行修复。目前市面上的资源热修复方案基本上删改都是参考Instant Run的实现。Instant Run实现过程要花费分为两部:

1、构造一一六个多新的AssetManager,并通过反射条用addAssetPath,把同类删改的新资源包加入到AssetManager中。一一六个多就得到了一一六个多含晒 所有新资源的AssetManager。

2.可能性厂商的自定义ROM,对少数机型暂不支持。兼容性差。

综上,对于中间的几种框架技术总结如下:

我们歌词 歌词 我们歌词 歌词 采用的是同类类修复反射注入法律土辦法 。把补丁so库的路径插入到nativeLibraryDirectories数组的最前面,就不能达到加载so库的前一天是补丁so库,而删改都是一一六个多so库的目录,从而达到修复的目的。

插件化和热修复技术是Android开发中比较高级的知识点,是中级开发人员通向高级开发中时需掌握的技能,插件化的知识可不时需查我我前一天的介绍:Android插件化。本篇重点讲解热修复,并对当前流行的热修复技术做一一六个多简单的总结。

Sophix:由补丁类的classLoader加载补丁类,在native层直接memcpy(smeth,dmth,sizeof(ArtMethod))替换整个artMethod的型态。初始化类删改都是为同类类分配空间,AllocArtMethodArray会紧挨着的new出来装入art中的法律土辦法 数组中。通过计算辅助类的前后一一六个多法律土辦法 的起始地址就可不时需计算出artMethod型态的大小了。

注:补丁类初始化时,也会分配买车人的artMethod空间,拿同类修复过的新ArtMethod去替换旧ArtMethod的内容,太满再管ArtMethod的型态。稳定性大大提高!

sophix采用的也是全量合成dex的技术,同类技术是从手淘插件化框架Atlas汲取的。直接利用Android一一六个多的类查找和合成机制,快速合成新的全量dex。如此一来,我们歌词 歌词 我们歌词 歌词 既不时需出理 合成时法律土辦法 数超过的情形,对于dex的型态而且用进行破坏性重构。

参考:http://www.jianshu.com/p/ed03e8e4b08f

Tinker集成Sophix集成

可能性父类补丁变成了增加了泛型则会增加Bridge法律土辦法 ,造成热部署失败。

将法律土辦法 从void get(B t) 变成 B extends Number void get(B t)法律土辦法 逻辑太满再居于变化,而且法律土辦法 的签名会居于变化,同类情形热修复如此意义,时需出理 同类情形的居于。

一旦补丁类中一直出现了法律土辦法 的增加和减少,就会因为同类类以及整个Dex的法律土辦法 数的变化。法律土辦法 数的变化伴随着法律土辦法 索引的变化,一一六个多在访问法律土辦法 时就无法正常地索引到正确的法律土辦法 了。

而热修复的开发流程显得更加灵活,太满再重新发版,实时高效热修复,太满再下载新的应用,代价小,最重要的是及时的修复了bug。

编译器可能性发现变量声明再加了泛型信息,编译器自动再加了check-cast的强制转换,可能性编译器会为泛型做类型检查,什么都自动的强制转换太满再一直出现ClassCastException。

3.合并时占用额外磁盘空间,对于多DEX的应用来说,可能性修改了多个DEX文件,就时需架构设计 多个patch.dex与对应的classes.dex进行合并操作时同类情形会更严重,而且合并过程的失败率也会更高。

类的构造函数会被编译器翻译成init法律土辦法 ,会先进行非静态field和非静态代码块的初始化。它们一直出现的顺序也是和在源码中一直出现的顺序一样。

执行new instance指令时,可能性类如此加载过,就尝试加载类。而且对对象内存分配,再而且执行invoke direct指令调用类的init构造函数进行初始化

同类法律土辦法 架构设计 删改的包很占用空间。而像一点方案,是先进行对资源包做差量,在运行时合成删改包再加载。一一六个多嘴笨 减少包的体积,而且在运行时多了合成的操作,耗费了运行时间喝内存。合成后的包也是删改的包,仍旧会占磁盘空间。

Lamda表达式具有函数式编程的特点,是Java中最接近闭包的概念。函数式接口:一一六个多接口具有唯一一一六个多抽象法律土辦法

Java中的Runable和Comparator删改都是典型的函数式接口

3.在ART模式下,可能性类修改了型态,就会一直出现内存错乱的大问题。为了出理 同类大问题,就时需把所有相关的调用类、父类子类等等删改加载到patch.dex中,因为补丁包异常的大,进一步增加应用启动加载的前一天,耗时更加严重。

AndFix不同于QQ空间超级补丁技术和微信Tinker通过增加或替换整个DEX的方案,提供了同类运行时在Native修改Filed指针的法律土辦法 ,实现法律土辦法 的替换,达到即时生效太满再重启,对应用无性能消耗的目的。其原理如下:



对于实现法律土辦法 的替换,时需在Native层操作,主要经过一一六个多步骤:

阿里的HotFix方案,相对于QQ空间超级补丁技术和微信Tinker来说,定居于紧急BUG修复的场景下,不能最及时的修复BUG,下拉补丁立即生效太满再等待时间。



从图中可不时需看完,我们歌词 歌词 我们歌词 歌词 重新编排了包中dex的顺序。一一六个多,在虚拟机查找类的前一天,会优先找到classes.dex中的类,而且才是classes2.dex、classes3.dex,也可不时需看做是dex文件级别的类插桩方案。同类法律土辦法 十分巧妙,它对旧包与补丁包中classes.dex的顺序进行了打破与重组,最终使得系统可不时需自然地识别到同类顺序,以实现类覆盖的目的。这可能性大大减少合成补丁的开销。

传统的底层替换法律土辦法 ,不论是Dexposed、Andfix可能性一点安全界的Hook方案,删改都是直接依赖修改虚拟机法律土辦法 实体的具体字段。同类,改Dalvik法律土辦法 的jni函数指针、改类或法律土辦法 的访问权限等等。一一六个多就带来一一六个多很严重的大问题,可能性Android是开源的,各个手机厂商都可不时需对代码进行改造,而Andfix里ArtMethod的型态是根据公开的Android源码中的型态写死的。可能性某个厂商对同类ArtMethod型态体进行了修改,就和一一六个多开源代码里的型态不一致,如此在同类修改过了的设备上,通用性的替换机制就会一直出大问题。这便是不稳定的根源。

final static基本类型/string类型最终引用的类型会被热部署替换掉。

final static引用类型可能性会被翻译到clinit法律土辦法 中,热部署失败。

如此一来,我们歌词 歌词 我们歌词 歌词 不仅出理 了兼容性大问题,而且可能性忽略了底层ArtMethod型态的差异,对于所有的Android版本删改都是再时需区分,代码量大大减少。即使前一天的Android版本不断修改ArtMethod的成员,而且保证ArtMethod数组仍是以线性型态排列,就能直接适用于将来的Android 8.0、9.0等新版本,太满再再针对新的系统版本进行适配了。

简单来讲,为了修复线上大问题而提出的修补方案,多多多线程 修补过程太满再重新发版!

final static基本类型执行const/4指令,操作数在dex中的位置(encoded_array_item)而且在opcode后一一六个多字节。

final static String类型执行const-string指令,本质同上只不过拿到的是字符串常量在dex文件型态中字符串常量区的索引id。dex文件有一块区域存储所有的字符串常量会被删改的加载到虚拟机内存中-字符串常量区。

final static引用类型执行sget指令,首先调用dvmDexGetResolveField看同类域是否前一天解析过,如此话语调用dvmDexResolveField尝试解析域,可能性同类静态域所在的类如此解析过,尝试调用dvmResolveClass,拿到同类sField,而且通过dvmDexGetResolveField(sField)获取同类静态值。

再来看看腾讯系三大类加载方案的实现原理。QQ空间方案会侵入打包流程,而且为了hack再加一点无用的信息,实现起来很不优雅。而QFix的方案,时需获取底层虚拟机的函数,欠缺稳定可靠,而且有个比较大的大问题是无法新增public函数。

而我们歌词 歌词 我们歌词 歌词 也对代码的底层替换原理重新进行了深入思考,从克服其限制和兼容性入手,以同类更加优雅的替换思路,实现了即时生效的代码热修复。sophix实现的是同类无视底层具体型态的替换法律土辦法 ,也而且把一一六个多一一六个多的逐一替换:

外部类&number。number即编译器根据匿名外部类一直出现在外部类中的顺序,依次累加。



动态注册的native法律土辦法 映射通过加载so库过程中调用JNI_OnLoad法律土辦法 调用完成,静态注册的native法律土辦法 映射是在该native法律土辦法 第一次执行的前一天才完成映射,当然前提是该so库可能性load过。

不过HotFix删改都是欠缺:

1.不支持新增字段,以及修改法律土辦法 ,而且支持对资源的替换。

so库的修复本质上是对native法律土辦法 的修复和替换。我们歌词 歌词 我们歌词 歌词 知道在JNI编程中,native法律土辦法 可不时需通过动态注册和静态注册同类法律土辦法 进行。动态注册的native法律土辦法 时需实现JNI_OnLoad法律土辦法 ,并肩实现一一六个多JNINativeMethod[]数组,静态注册的native法律土辦法 时需是Java+类删改路径+法律土辦法 名的格式。

类加载方案的原理是在app重新启动后让Classloader去加载新的类。可能性在app运行到一半的前一天,所有时需居于变更的类可能性被加载过了,在Android上是无法对一一六个多类进行卸载的。可能性不重启,一一六个多的类还在虚拟机中,就无法加载新类。而且,还可不可以了在下次重启的前一天,在还没走到业务逻辑前一天抢先加载补丁中的新类,一一六个多后续访问同类类时,就会Resolve为新类。从而达到热修复的目的。

Lamada表达式和匿名外部类的区别:

1.this关键字指包围Lamada表达式的类而删改都是指向匿名外部类买车人

2.编译法律土辦法 ,Java编译器将Lamda表达式编译成类的私有法律土辦法 ,使用了Java7的invokedynamic动态绑定同类私有法律土辦法 。而匿名外部类则是生成外部类&number的新类.编译器删改都是在类下生成lamda$main$*{ }私有静态法律土辦法 ,同类法律土辦法 实现了lamda表达式的逻辑,引用的变量删改都是变成法律土辦法 的参数。

外部类会被编译器生成同外部类一样的顶级类。只不过非静态外部类会持有外部类的引用。这也是Android性能优化建议Handler使用静态外部类,出理 外部类Activity还可不可以了被回收因为造成OOM。

2.时需给应用开启新的多多多线程 不能进行合并,而且很容易可能性内存消耗等因为合并失败。

外部类和外部类互相访问private法律土辦法 和字段时,会自动在对应类为对方生成public的access&**法律土辦法 。

QQ空间超级补丁采用的插桩法律土辦法 ,入侵打包流程,单独放一一六个多帮助类在独立的dex中让一点类调用,阻止类在dexopt时被打伤CLASS_ISPREVERIFIED标记。其原理如下图:



加载补丁dex得到dexFile对象作为参数构建一一六个多Element对象插入到dexElement数组最前面。

Tinker提供差量包,整体替换dex的方案。将patch.dex与应用的class.dex合并生成一一六个多删改的dex,加载删改的dex得到dexFile对象为参数构建一一六个多Element对象替换dexElements数组。

官方multiDex如此补丁查询更新,下载补丁待下次启动时生效。

其流程可不时需总结为如下图所示:

当前热门的热修复技术有:

不支持对静态字段和静态代码块的修改,会因为热部署失败,还可不可以了冷启动生效。支持非静态字段和非静态代码块修改,热部署而且将init构造函数作为普通的法律土辦法 变更。

代码修复有两大主要方案:同类是阿里系的底层替换方案,另同类是腾讯系的类加载方案。底层替换方案限制颇多,但时效性最好,加载轻快,立即见效。类加载方案时效性差,时需重新冷启动不能见效,但修复范围广,限制少。

针对中间的大问题,腾讯出了QFix方案。

在native层提前调用dvmResolveClass,是的在dvmResolve中调用dvmDexGetResolve不为null,也出理 了校验一致性的大问题。

同类方案要求传递的在多dex情形下,referrer类时需跟patch类是同一一六个多dex。fromUnverifiedConstant时需为true。referrer时需提前加载。

这方案时需一点大问题,在dexopt前一天绕过,而且dexopt会改变什么都一一六个多的逻辑,一点odex层面的优化会写死字段和访问法律土辦法 的偏移。这会造成很严重的BUG。

微信的Tinker方案是删改的全量dex加载,而且可谓是将补丁合成做到了极致,然而我们歌词 歌词 我们歌词 歌词 发现,精密的武器删改都是随后 适用于所有战场。Tinker的合成方案,是从dex的法律土辦法 和指令维度进行全量合成,整个过程删改都是买车人研发的。

不过细心的读者会发现,QQ空间超级补丁在使用 过程中还居于如下大问题:

1.不支持即时生效,时需通过重启不能生效。

在正常软件开发流程中,线下开发->上线->发现bug->紧急修复上线。不过对于同类法律土辦法 代价太满再 。

1.与超级补丁技术一样,不支持即时生效,时需通过重启应用的法律土辦法 不能生效。

Java字节码中不含晒 泛型类型信息,太满再再区别类型定义可不时需限定泛型类型

在HostSpot VM下解释class文件的lamda表达式:

invokeDynamic指令调用java/lang/invoke/LamdaMetafactory的metafactory同类静态法律土辦法 。同类法律土辦法 会在运行时生成实现函数式接口的具体类,同类具体类会调用那个静态私有法律土辦法 。

在Android虚拟机下解释dex文件中的lamda表达式:则是在优化成dex文件的前一天就生成了同类具体类。

这是同类方案的固有限制,而底层替换方案最为人诟病的地方,在于底层替换的不稳定性。

2、找到所有前一天引用到原AssetManager的地方,通过反射,把引用处替换为AssetManager

final static引用类型初始化仍在clinit中final static基本类型和String类型,类加载初始化dvminitClass在执行clinit法律土辦法 前一天,先执行initSFields,同类法律土辦法 为static域赋予默认值。引用类型默认NULL,final static修饰的基本类型和String类型会在这里初始化赋值。

2.为了实现修复同类过程,时需在应用中加入一一六个多dex!dalvikhack.dex中只一一六个多多类,对性能影响不大,而且对于patch.dex来说,修复的类到了一定数量,就时需花不少的时间加载。对手淘同类航母级应用来说,启动耗时增加2s以上是还可不可以了够接受的事。

要弄清热修复技术的原理,就要先弄清Android的ClassLoader机制,相关文章可不时需阅读前一天的介绍:ClassLoader类加载机制。Android的ClassLoader分为PathClassLoader和DexClassLoader,它们都都继承自BaseDexClassLoader,其中PathClassLoader用来加载系统类和应用类;DexClassLoader用来加载jar、apk、dex文件。同类下面要介绍的阿里的Andfix和Sophix的原理如下:

热门

热门标签