# This demo implementation principle comes from
Https://github.com/dodola/HotFix
https://zhuanlan.zhihu.com/p/20308548
# Anti class function, and its principle
For example, A,b,c is a three class, they are packaged into the same Dex file when the APK file is generated, and when the APK is released to run for a while to find a bug, now fix the bug using the fix in the link above. As stated in this article, if you rewrite the class A directly and use the runtime to dynamically load and insert the Dex file of the repaired Class A in front of the load chain, a can be repaired. However, since the class in the Dex file is not dependent on the external file during optimization, the class inside the Dex file is tagged with a class_ispreverified tag so that when Class B is reused with the repaired Class A, because it is in another Dex file, A run-time error is reported. So in class B, adding a line of code makes it dependent on the anti class in another Dex, so that B is not labeled. It is important to note that the APK running in the real environment, because it is not certain which (which) class will have problems in the future, so in order to fix it in the future (they), the above A,b,c class should be added to reference anti code; Because the Dex in anti is loaded in the OnCreate method of the application class, you should not refer to the OnCreate class before the anti method of the application class.
# Production of Anti_dex.jar and Bug_dex.jar
Main process: Dex, Java-class
Java-class, you can use the IDE, such as as, or the direct command line to use the compilation tools provided by the JDK
Javac-source 1.7-target 1.7–CP. –d. <MAIN_CLASS>, the command needs to be executed in the same level directory of the package, and Main_class contains the package path name.
Dex, class, can use the DX tool, like
DX--dex--output=classes_dex.jar <CLASS_PATH>
# test Code Writing
@Override Public voidonCreate () {Super. OnCreate (); File Dexpath=NewFile (Getdir ("Dex", Context.mode_private), "Anti_dex.jar"); Utils.preparedex ( This. Getapplicationcontext (), Dexpath, "Anti_dex.jar"); Hotfix.patch ( This, Dexpath.getabsolutepath (), "Hotfix.test.com.example.didi.applicationtesthotfix.Anti"); Dexpath=NewFile (Getdir ("Dex", Context.mode_private), "Bug_dex.jar"); Utils.preparedex (Getapplicationcontext (), Dexpath,"Bug_dex.jar"); Hotfix.patch (Getapplicationcontext (), Dexpath.getabsolutepath (),"Hotfix.test.com.example.didi.applicationtesthotfix.BugClass"); Try{Class<?> clazz = Class.forName ("Hotfix.test.com.example.didi.applicationtesthotfix.Anti"); Equalloader (Clazz); LOG.E ("Ruby", "Anti ' s ClassLoader ' hashcode" + clazz.getclassloader (). Hashcode () + "," +Clazz.getclassloader (). GetClass (). GetName ()); Class<?> CLA = Class.forName ("Hotfix.test.com.example.didi.applicationtesthotfix.BugClass"); Equalloader (CLA); LOG.E ("Ruby", "Bugclass ' s ClassLoader ' hashcode" + cla.getclassloader (). Hashcode () + "," +Cla.getclassloader (). GetClass (). GetName ()); } Catch(Exception e) {}}
# Eliminate anti's compilation script
Because Anti.class cannot be packaged into a Dex file with AS, it is necessary to remove the Anti.class after compiling the class file of the project into Dex, and then package it into an APK file by using the AS-is-compiled class file and the packaged resource file package on its own command line.
#Package class file generates DEX filesDX=/USERS/DIDI/LIBRARY/ANDROID/SDK/BUILD-TOOLS/23.0.3/DX classes=build/intermediates/classes/release/$DX--dex--output=classes.dex$classes#package res/assets/file into Resources-release.ap_ file (as completed)#package Resources-release.ap_ and Classes.dex files into hotfix-unsign.apkSdklib=/users/didi/library/android/sdk/tools/lib/sdklib.jarapk=com.android.sdklib.build.Apkbuildermainapp/build/intermediates/resresources=build/intermediates/res/resources-release.Ap_java-classpath$sdklib $apkHotfix-unsign.apk-u-Z$resources-F classes.Dex#SignatureKeystore=/users/didi/documents/didichuxing/driver/lulei.Keystorealia=LULEIPSW=Demodebugjarsigner=/System/library/frameworks/javavm.framework/versions/ Current/commands/Jarsigner$jarsigner-digestalgSHA1-sigalg Md5withrsa-keystore$keystore-storepass$PSW-keypass$PSW-signedjar hotfix-sign.apk hotfix-unsign.apk$alia
# The reason for the dynamic hot fix not working at runtime
protectedClass<?> LoadClass (String className,BooleanResolvethrowsclassnotfoundexception {Class<?> Clazz =Findloadedclass (className); if(Clazz = =NULL) {ClassNotFoundException suppressed=NULL; Try{clazz= Parent.loadclass (ClassName,false); } Catch(ClassNotFoundException e) {suppressed=e; } if(Clazz = =NULL) { Try{clazz=Findclass (className); } Catch(ClassNotFoundException e) {e.addsuppressed (suppressed); Throwe; } } } returnClazz;}
From the above ClassLoader source, you can see that when looking for a class, we first look at whether the class is loaded in memory, so if you have used Class A before loading the repaired class file A, the scheme fails. So the program will load the Dex of a in application's OnCreate method beforehand.
# The difference between "bytecode modification" and "compile dependent" scenarios
There is no difference in principle!
# Google subcontracting scheme, what is the ghost, what is the subcontracting strategy?
I still don ' t know!
# Huawei I7-ath-al00 Android version 5.1.1 Why not insert anti code?
What? fuck!!!
# Reflection
Although a custom dexclassloader is used to reload the repaired class file from the file into memory, But because the scenario is to assign the dexfile of Dexclassloader (the parent Class) to Pathclassloader (the Pathlists member of the parent class Baseclassloader) by reflection, So look at the classloader of the repaired class and still show the pathclassloader of the system.
Demo code please refer to GitHub address
Android based on the repair of subcontracting scheme