In Android development , we often encounter the concept of hot updates, and how is this hot update specifically implemented? Today on the Internet to see a big God to share the Heat update related implementation principles and implementation code, feel gray often good, share to the vast number of farmers look looks.
ClassLoader
The underlying language of Android is Java, and Java loads the corresponding class at run time through ClassLoader, and ClassLoader itself is an abstraction, Android uses the Pathclassloader class as the default class loader for Android.
What is Pathclassloader again? Pathclassloader actually implemented is simply to load the class file from the file system. Pathclassloade itself inherits from the Basedexclassloader,basedexclassloader rewrite Findclass method, which is the core of ClassLoader, the specific code is as follows:
@Override
Protected class<?> Findclass (String name) throws ClassNotFoundException {
list<throwable> suppressedexceptions = new arraylist<throwable> ();
Class C = pathlist.findclass (name, suppressedexceptions);
if (c = = null) {
ClassNotFoundException Cnfe = new ClassNotFoundException ("didn ' t find class/" "+ Name +"/"On Path:" + pathList);
for (Throwable t:suppressedexceptions) {
cnfe.addsuppressed (t);
}
Throw Cnfe;
}
return C;
}
Looking at the code above, we can clearly see that basedexclassloader the Findclass method to the Findclass method of the PathList object, The PathList object is new in the constructor of Basedexclassloader, and its type is dexpathlist. Look at the Dexpathlist.findclass source code is how to do:
Public Class Findclass (String name, list<throwable> suppressed) {
for (Element element:dexelements) {
Dexfile dex = Element.dexfile;
if (dex! = null) {
Class clazz = dex.loadclassbinaryname (name, Definingcontext, suppressed);
if (clazz! = null) {
return clazz;
}
}
}
if (dexelementssuppressedexceptions! = null) {
Suppressed.addall (Arrays.aslist (dexelementssuppressedexceptions));
}
return null;
}
Simply traversing the dexelements list, and then loading the class by calling the Loadclassbinaryname method on the Element.dexfile object, if the return value is not NULL, indicates that the load class succeeds and returns the class object. The Dexelements object is initialized in the constructor of the Dexpathlist class.
this.dexelements = Makedexelements (Splitdexpath (Dexpath), optimizeddirectory, suppressedexceptions);
What Makedexelements does is traverse through the Dexpath and load each Dex file at once.
The above analysis of the loading process of the class in Android, it can be seen that the Dexelements list in the Dexpathlist object is a core of class loading, if a class can be loaded successfully, Then its Dex must appear in the dexelements corresponding to the Dex file, and dexelements in the order of occurrence is also important, in the dexelements before the Dex will be loaded first, once the class is loaded successfully, will immediately return, that is to say , if we want to do hotpatch, make sure our hotpacth dex file appears in front of the dexelements list.
To implement a hot update, we need to change the PathClassLoader.pathList.dexElements at runtime, because these properties are private and therefore need to be modified by reflection. In addition, when constructing our own Dex file corresponding to the dexelements array, we can also take a more trickery way, that is, by constructing a Dexclassloader object to load our Dex file, and call once Dexclassloader.loadclass (Dummyclassname);
For example, DexClassLoader.pathList.dexElements will include our Dex, by inserting dexClassLoader.pathList.dexElements into the system default ClassLoader.pathList.dexE In front of the lements list, you can let the system load the classes in our Dex first, allowing for a hot update. Let's take a look at some of the code below:
private static synchronized Boolean injectAboveEqualApiLevel14 (
String Dexpath, String Defaultdexoptpath, String Nativelibpath, String dummyclassname) {
LOG.I (TAG, "--injectAboveEqualApiLevel14");
Pathclassloader Pathclassloader = (pathclassloader) DexInjector.class.getClassLoader ();
Dexclassloader Dexclassloader = new Dexclassloader (Dexpath, Defaultdexoptpath, Nativelibpath, PathClassLoader);
try {
Dexclassloader.loadclass (Dummyclassname);
Object dexelements = Combinearray (
Getdexelements (Getpathlist (Pathclassloader)),
Getdexelements (Getpathlist (Dexclassloader)));
Object pathList = getpathlist (Pathclassloader);
SetField (PathList, Pathlist.getclass (), "dexelements", dexelements);
} catch (Throwable e) {
E.printstacktrace ();
return false;
}
LOG.I (TAG, "<--injectAboveEqualApiLevel14 End.");
return true;
}
The above is the Heat update related principles and implementation code, hope to help you better grasp this part of the knowledge ~ ~ If there is not clear, you can also go directly to the official web site to see the relevant documents.
Related article: What are the basic elements of the Android UI design
How is the Android hot update implemented?