Quickpatch Project Address:
Https://gitee.com/egg90/QuickPatch and Https://github.com/eggfly/QuickPatch sync updates
Similar to the U.S. regiment robust pile hot repair, but the code readability is strong, still continue to improve, Todo list in the project Readme
Quickpatch Project Introduction
Young man's first Android pile hot fix frame
Based on the function of the pile, the compatibility is good (Android version upgrade does not need to be modified), support hot update without restarting the app, reference to the American regiment robust pile hot repair framework, streamlining many implementation details, code readability high
Word principle
Simply put, you can dynamically replace the implementation at runtime without restarting by inserting an if judgment and a proxy proxy at the head of each function at compile time. The code is as follows:
protected void onCreate(Bundle savedInstanceState) { if (_QPatchStub != null) { // _QPatchStub.proxy() will check method existance and call it MethodProxyResult proxyResult = _QPatchStub.proxy(this, "onCreate", "(Landroid/os/Bundle;)V", new Object[]{savedInstanceState}); if (proxyResult.isPatched) { return; } } // origin implementation below super.onCreate(savedInstanceState); // ...}
Design ideas
- The difference between quickpatch and robust is that robust's compile and Dex phases are handled using ASM and Smali respectively, Quickpatch only in Gradle compiled Java to class stage using javassist processing, logic is simple
- Automatic generation of DEX patches (high complexity, poor code readability) is not supported, so patches need to be generated manually, but a patch template is provided, which is easy to write.
- For super handling use native call callnonvirtual# #TYPE # #Method () Series method implementation
- Plan to support constructors and add hot fixes for member functions
- May plan to support hot fixes for non-Android pure Java code
DEMO
Instructions for use
- Open a line in App/build.gradle Apply plugin: ' Quickpatch.gradleplugin '
- Then use Androidstudio or./gradlew to perform the following tasks:
./gradlew gradleplugin:uploadArchives # 编译插桩插件./gradlew app:installDebug # 使用插件编译app代码并插桩
- To make it easy to click the Enable Patch button in the app to simulate the patch loading effect, you actually loaded the packaged Qpatch class in the APK with the original ClassLoader.
- The same package name suffix is _qpatch class is a patch class, such as Mainactivity class patch class corresponding name is Mainactivity_qpatch
- The framework code then loads the DEX using a new ClassLoader, and then the reflection recognizes and finds out if the corresponding function exists, and the logic inside the new function is called if it exists.
- The patch file name is typically Patch.dex, and generating Dex requires manual use of commands such as DX--dex--output=patch.dex mainactivity_qpatch.class
- The patch file needs to be manually placed under the SD card, such as ADB push patch.dex/sdcard/
- Then click the Enable Patch button in the app to load the patch in real time and see that the PID doesn't change
Performance optimization Ideas
- Reduce the loss of all function calls without patches
- Reduce the loss of patches, but not go to the class that the patch involves
- Reduce patch, go to patch class, but not go to the patch function loss
- Reduce the loss of patches when you go to the patch class and go to the patch function
- The optimization patch function does not contain reflection, and these three cases contain native reflection or Java reflection
Introduce yourself to an Android plug-in hot fix Framework project Quickpatch