This article is about the fundamentals of implementing thermal updates in Android.
First, ClassLoader
We know that Java loading the corresponding class at runtime is implemented through ClassLoader, ClassLoader itself is an abstraction, and Android uses the Pathclassloader class as the default ClassLoader for Android, Pathclassloader actually realizes is simply to load the class file from the file system. The Pathclassloade itself inherits from Basedexclassloader,basedexclassloader and rewrites the Findclass method, which is the core of ClassLoader.
@Override
protected class> findclass (String name) throws ClassNotFoundException {
List Suppressedexceptions = new ArrayList ();
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;
}
Look at the source, Basedexclassloader the Findclass method is delegated to the PathList object Findclass method, the PathList object is in the Basedexclassloader constructor new out, Its type is dexpathlist. Look at the Dexpathlist.findclass source code is how to do:
Public Class Findclass (String name, List 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;
}
The direct is to traverse the dexelements list and then load the class by calling the Loadclassbinaryname method on the Element.dexfile object, if the return value is not NULL, the load class succeeds, and the class object is returned. The Dexelements object is initialized in the constructor of the Dexpathlist class.
this.dexelements = Makedexelements (Splitdexpath (Dexpath), optimizeddirectory, suppressedexceptions);
What makedexelements do is traverse the dexpath we pass and load each Dex file at a time.
Second, realize
This analysis of the process of loading the classes in Android shows that the Dexelements list in the Dexpathlist object is a core of class loading, and if a class can be loaded successfully, Then it's Dex will appear in the dexelements corresponding to the Dex file, and the order in the dexelements is also very important, in dexelements before the presence of Dex will be first loaded, once the class is loaded successfully, it will return immediately, that is to say , if we want to do hotpatch, we must ensure that our Hotpacth Dex file appears in front of the dexelements list.
To implement hot updates, we need to change PathClassLoader.pathList.dexElements at run time, because these properties are private and therefore need to be modified by reflection. In addition, we can take a tricky approach by constructing a dexelements array of our own Dex files, which is to load our Dex files by constructing a Dexclassloader object. and call once Dexclassloader.loadclass (Dummyclassname);
method, so that DexClassLoader.pathList.dexElements, it will contain our Dex, by inserting dexClassLoader.pathList.dexElements into the system default ClassLoader.pathList.dexEle Before the ments list, you can give the system priority to load the classes in our Dex, allowing for hot updates.
Here's a partial code
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, "
Android to achieve the principle of hot update first for everyone to introduce this, we can combine the knowledge accumulated at ordinary times, consult related books for in-depth study, I hope we can have some harvest.