Notes in-depth exploration of the principle of Android hot repair technology

Notes organized by Ali's e-book "In-depth exploration of the principles of Android hot repair technology"


1. Introduction of thermal repair technology

  1. Two main solutions for code repair
    • Bottom-level replacement scheme: there are many restrictions, but the timeliness is good, and the effect is immediate
    • The class loading scheme has poor timeliness and requires a cold restart to take effect, but there are few restrictions
  2. Code fix underlying replacement scheme
    • The low-level replacement scheme is to directly replace the original method in the loaded class.
    • It is not possible to add or remove methods and fields to the original class, because this will destroy the structure of the original class.
    • The increase or decrease of methods will lead to changes in the number of methods in this class and the entire Dex, along with the changes in the method index, so that the correct method cannot be indexed normally when accessing the method;
    • Fields increase or decrease, the index of all fields will change;
    • The traditional bottom-level replacement scheme directly relies on modifying specific fields in the virtual machine method entity. It is based on the Android open source version. If the manufacturer modifies the virtual machine method entity, the replacement mechanism may have problems;
  3. Code Repair Class Loading Scenario
    • The principle of the class loading scheme is to let the Classloader load new classes after the app is restarted.
    • When the app is halfway running, all the classes that need to be changed have been loaded, and Android cannot unload a class. If it is not restarted, the original class is still in the virtual machine, and the new class cannot be loaded.
    • Only in the next restart, the new classes in the patch are preemptively loaded before the business logic is reached, and subsequent accesses are new classes.
    • The optimal granularity of dex comparison should be at the granularity of the class
    • Sophix also uses the technology of fully synthesizing dex. It can be regarded as a class instrumentation scheme at the dex file level. Sophix breaks and reorganizes the order of classes.dex in the old package and patch package, so that the system can naturally recognize this order to achieve the purpose of class overriding
  4. Resource Repair
    • Many resource hot repair solutions on the market use the implementation of Instant Run
    • Resource repair steps in Instant Run:
      1. Construct a new AssetManager, call addAssetPath through reflection, and add this complete new resource package to the AssetManager. In this way, an AssetManager containing all new resources is obtained.
      2. Find all previous references to AssetManager, and replace references to AssetManager through reflection.
    • Sophix resource hot repair does not use the Instant Run technology, but constructs a resource package with a package id of 0x66. This package only contains the changed resource items, and then directly addAssetPath in the original AssetManager. This package can be. There is no need to change the AssetManager A reference to the object.
      1. The package id of the patch package constructed by Sophix is ​​0x66, which does not conflict with the already loaded 0x7f, so it can be directly added to the existing AssetManager and used directly.
      2. The Sophix resource patch package only contains new resources and resources whose original content has changed.
  5. SO library fix: essentially a fix and replacement of native methods

Sophix采用的是类似类修复反射注入方式,把补丁so库的路径插入到nativeLibraryDirectories数组的最前面, 这样加载so库的时候就是补丁so库而不是原来的so库

2. Code hot repair technology

  1. Bottom Hot Replacement Principle
    • Android's java operating environment, the dalvik virtual machine is used below 4.4, and the art virtual machine is used above 4.4.
    • In various Android hot repair solutions, Andfix takes effect immediately. The method used by Andfix is ​​to directly replace all methods in the native layer in the loaded class, and modify it on the basis of the original class.
    • Taking art and Android 6.0 as an example, each Java method corresponds to an ArtMethod object in art, and ArtMethod records all the information of this Java method, including the class to which it belongs, access rights, code execution address, etc.
    • Andfix will replace all field values ​​in the ArtMethod instance corresponding to an old Java method with the values ​​of the new method , so that all places where the old method is executed will get the execution entry of the new method, the class to which it belongs, the method index, and the dex to which it belongs . Calling the old method executes the logic of the new method .
  2. Underlying Hot Replacement Compatibility Roots
    • Almost all native replacements on the market are hard-coded ArtMethod structures.
    • The hard-coded ArtMethod structure is exactly the same as the Android open source version, but each manufacturer can modify the ArtMethod, then on the modified device, the native replacement scheme on the market ( the new method associated with the hard-written ArtMethod in the scheme) properties assigned to the ArtMethod instance in the device ) will cause problems because the index of the same field in the two ArtMethods is different
  3. Break through the underlying hot-replacement compatibility problem
    • The replacement at the native level is essentially to replace all fields of the ArtMethod instance.
    • As long as the ArtMethod is replaced as a whole, the compatibility problem can be solved.
    • ArtMethod instances are arranged in a tight line, so the size of an ArtMethod is the difference between the starting addresses of the ArtMethod instances corresponding to its two adjacent methods.
  4. The underlying replacement schemes, including Sophix, can only support method replacement, and do not support adding or subtracting methods and fields in the patch class.
    • Adding or subtracting methods in the patch class will lead to changes in the number of methods in this class and the entire dex, and the change in the number of methods is accompanied by changes in the method index, so that the correct method cannot be guided normally when the method is called.
    • Adding or removing fields in the patch class will also cause the indexes of all fields to change.
  5. You don't know Java
    • The inner class will be compiled into a top-level class that is the same as the root outer class at compile time;
    • Non-static inner classes hold references to external classes, and static inner classes do not hold references to external classes . Therefore, in android performance optimization, it is recommended that the implementation of custom Handlers use static inner classes as much as possible to prevent memory leaks caused by the failure of external Activity classes to be recycled. .Custom Handler uses static inner class to avoid memory leak
    • Between the inner class and the outer class, access each other's private properties and methods, during compilation:
      • The outer class accesses the private members and methods of the inner class, and the access&** method is automatically generated for the inner class during compilation
      • The inner class accesses the private properties and methods of the outer class, and access&** methods are also generated during compilation to provide the inner class
    • For the same class and its inner classes, if the old code does not access the other party's private properties/methods, and the new code has access to the other party's private properties/methods, if the generation of access& cannot be avoided, the number of methods will change, resulting in hot fixes. Failed . To avoid generating access & methods requires:
      • All properties and methods of the outer class are changed to public or protected;
      • All properties and methods of the inner class are changed to public or protected;
    • During compilation, according to the order in which the anonymous inner class appears in the outer class, the names of the anonymous inner classes are accumulated in order: outer class name & number
      • The name of the external class is OutClass, and the names of the corresponding internal classes during compilation are: OutClass&1, OutClass&2 ,-----
      • In order to achieve hot repair, external classes should try to avoid adding and reducing anonymous inner classes;
      • Unless the anonymous inner class is added to the end of the outer class, it will not affect the name of the previously added anonymous inner class, otherwise it will cause the hot repair to fail;
    • Java primitive types: double, float, byte, short, int, long, char, boolean
      • If the type of a constant is a Java primitive type, or String, in order to optimize performance, it should be modified with static final;
      • static final reference type without any optimization effect.
      • Because the original types and String constants modified by static final are assigned when the class to which they belong is initialized, and are read directly in memory;
      • For static final reference type constants, the initialization is in the clinit method, which essentially obtains the value through the sget-object instruction, and there is no optimization in the performance of the virtual machine;
  6. Cold-start class loading implementations on the market
    • 1: Using the dex instrumentation method, put a separate helper class in a separate dex for other classes to call. Finally, load the patch dex to get the dexFile object, and use dexFile as a parameter to construct an Element object and insert it at the top of the dexElements array
    • 2: Provide a dex differential package to replace the dex as a whole: the differential patch.dex and the applied classes.dex synthesize the complete dex. Load the complete dex to get the dexFile object, build an Element object as a parameter, and then replace the old dexElements as a whole array
    • The disadvantage of 1 is: Dalvik affects the class loading performance, and the class address under Art is written to death, resulting in the parent class and reference must be included, and the patch package is very large
    • The disadvantage of 2 is: the merging of dex, the memory consumption is on the vm heap, which can easily lead to OOM, and the merging fails
  7. The code repair cold start scheme adopted by Sophix
    • Use the full Dex solution under Dalvik;
    • In essence, the virtual machine already supports multi-dex loading under Art, as long as the patch dex is used as the main dex (classes)
  8. Sophix's full Dex solution idea under Dalvik
    • In the baseline package dex, remove the classes contained in the patch package dex; in this way, the patch + removes the baseline package of the classes contained in the patch, which is equal to all the classes in the new app ;
    • Sophix does not remove all the information of a certain class from the baseline dex, but only removes the defined entry, so that the definition of this class cannot be found when parsing the baseline dex; this will not cause all parts of the dex to occur. changes, preventing a large number of adjustments to the offset.
    • As long as all dexes are loaded, classes that do not exist in a single dex can be found in other dexes during runtime. The classes in the patch and the classes in the baseline can access each other

3. Resource thermal repair technology

Android资源的热修复,就是在app不重新安装的情况下,利用下发的补丁包直接更新app中的资源 Sophix's resource hotfix solution

1:构造一个 package id 为0x66的资源包,这个包里只含有变更的资源,以及新增资源;
2:然后直接在原有AssetManager上调用addAssetPath加入这个资源包即可;

因为我们补丁包的id和已经加载的0x7f冲突,所以直接加入原有AssetManager即可直接使用

4. SO library thermal repair technology

without

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325966599&siteId=291194637