An overview of the
Hotfixes have been around for so long that it’s a bit late to start talking about them, but here’s a simple idea. Purpose? Algorithms help you dig into, or review, the “class loading” mechanism, which is fun.
Load model (parent delegate)
Schematic diagram
The proxy pattern
Android class loading uses parental delegation, which delegates requests to the parent loader before processing them. When it comes to delegating, it’s easy to think of “proxy mode,” and in fact for a ClassLoader, its relationship with parent is really a proxy/delegate relationship, giving access control to the propped class (if it’s already loaded the class, it won’t continue delegating requests to parent). From this perspective, it is indeed the proxy model.
Decorator pattern
For example, DexClassLoader will enable the ClassLoader to load class classes from APK, DEX, JAR, etc. In this regard, it is decorator mode.
Parental delegation pattern, that is, with control properties, but also has the ability to increase the behavior. In terms of performance, it’s generally hard to tell the difference. In fact, we use design patterns to solve some problems, and to think about it from that perspective, let’s look at which design patterns can solve class loading problems. What are some of the problems you might encounter with class loading?
- Protect the system class from core classes being changed in series
- Prevent reloading
Based on these two problem points, we found that class loading urgently needs to address access control rather than capability enhancement. So we say that the parent delegate mechanism is a proxy pattern.
The loading process
Hot repair
From the loading model above, we know that class loading requests are given priority to parent. With this mechanism, we just need to insert our custom ClassLoader into the parent position of our APP’s PathClassLoader. This will intercept all class loading requests.
The above code actually encounters a problem such as HomeActivity extends BaseActivity, which we heat fix, but with the above loading we get an exception that the class cannot find. Reason: For HomeActivity to be loaded by MyDexClassLoader, all unloaded classes used by HomeActivity will be loaded directly by the class loader. There are two solutions to this situation:
1. Reset the classLoader by reflection for classes loaded by MyDexClassLoader
2. Change the class loading model
conclusion
The overall process is relatively simple, and there are not many reflection points involved. If you encounter reflection failure of Android P and later versions, you can use meta reflection to deal with it.