介绍自己的一个Android插桩热修复框架项目QuickPatch
2018-08-27 10:54
681 查看
QuickPatch项目地址:
https://gitee.com/egg90/QuickPatch 和 https://github.com/eggfly/QuickPatch 同步更新
类似于美团的Robust插桩热修复,但是代码可读性比较强,还在继续完善,todo list在项目README里
基于函数插桩,兼容性好(Android版本升级不需要做修改),支持热更新无需重启app,参考了美团的Robust插桩热修复框架,精简了很多实现细节,代码可读性高
不支持自动生成dex补丁(复杂度高,代码可读性差),所以需要手动生成补丁,但是提供了补丁类模版,写起来很方便
对于super的处理使用native调用CallNonVirtual##TYPE##Method()系列方法实现
计划支持构造函数和增加成员函数的热修复
可能计划支持非Android的纯Java代码的热修复
然后使用AndroidStudio或者./gradlew执行下面任务:
为了方便点击app内的Enable Patch按钮可以模拟补丁加载效果,实际上是使用原本的ClassLoader加载了apk内打包好的的QPatch类
同包名下后缀是_QPatch的类是补丁类,如MainActivity类的补丁类对应名字是MainActivity_QPatch
接下来框架代码会使用一个新的ClassLoader加载dex,然后反射识别并查找相应的函数是否存在,如果存在则新的函数里面的逻辑会被调用
补丁文件名一般是patch.dex, 生成dex需要手动使用命令,比如dx --dex --output=patch.dex MainActivity_QPatch.class
补丁文件需要手动放置到sd卡下,比如adb push patch.dex /sdcard/
然后点击app内的Enable Patch按钮即可实时加载补丁,看到pid不会有变化
减少有patch时,但没有走到patch涉及到的类时的损耗
减少有patch时,走到patch类,但是没走到patch函数时的损耗
减少有patch时,走到patch类,并走到patch函数时的损耗
优化patch函数内不包含反射,和包含native反射或java反射的这三种情况
https://gitee.com/egg90/QuickPatch 和 https://github.com/eggfly/QuickPatch 同步更新
类似于美团的Robust插桩热修复,但是代码可读性比较强,还在继续完善,todo list在项目README里
QuickPatch项目介绍
年轻人的第一个Android插桩热修复框架基于函数插桩,兼容性好(Android版本升级不需要做修改),支持热更新无需重启app,参考了美团的Robust插桩热修复框架,精简了很多实现细节,代码可读性高
一句话原理
简单地讲,就是通过编译时在每个函数的头部插入一个if判断和一个proxy代理,就可以在运行时动态替换实现,无需重启。代码如下: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); // ... }
设计思路
QuickPatch和美团Robust的区别是,Robust的编译和dex阶段分别使用ASM和Smali做了处理,QuickPatch仅在gradle编译java到class阶段使用Javassist处理,逻辑简单不支持自动生成dex补丁(复杂度高,代码可读性差),所以需要手动生成补丁,但是提供了补丁类模版,写起来很方便
对于super的处理使用native调用CallNonVirtual##TYPE##Method()系列方法实现
计划支持构造函数和增加成员函数的热修复
可能计划支持非Android的纯Java代码的热修复
DEMO
使用说明
打开app/build.gradle中的一行apply plugin: 'quickpatch.gradleplugin'然后使用AndroidStudio或者./gradlew执行下面任务:
./gradlew gradleplugin:uploadArchives # 编译插桩插件 ./gradlew app:installDebug # 使用插件编译app代码并插桩
为了方便点击app内的Enable Patch按钮可以模拟补丁加载效果,实际上是使用原本的ClassLoader加载了apk内打包好的的QPatch类
同包名下后缀是_QPatch的类是补丁类,如MainActivity类的补丁类对应名字是MainActivity_QPatch
接下来框架代码会使用一个新的ClassLoader加载dex,然后反射识别并查找相应的函数是否存在,如果存在则新的函数里面的逻辑会被调用
补丁文件名一般是patch.dex, 生成dex需要手动使用命令,比如dx --dex --output=patch.dex MainActivity_QPatch.class
补丁文件需要手动放置到sd卡下,比如adb push patch.dex /sdcard/
然后点击app内的Enable Patch按钮即可实时加载补丁,看到pid不会有变化
性能优化思路
减少没有patch的时候所有函数调用损耗减少有patch时,但没有走到patch涉及到的类时的损耗
减少有patch时,走到patch类,但是没走到patch函数时的损耗
减少有patch时,走到patch类,并走到patch函数时的损耗
优化patch函数内不包含反射,和包含native反射或java反射的这三种情况
相关文章推荐
- 介绍自己的一个Android插桩热修复框架项目QuickPatch
- Android--项目框架介绍
- 通过个人介绍,侧面谈下自己操作过的一个项目
- 【Android开发经验】来,咱们自己写一个Android的IOC框架!
- 自己搭建Android项目框架必备的框架与第三方应用
- 01-zendframework框架介绍---创建一个框架项目
- 介绍本人的一个Android项目(附源代码)
- Android Hotpatch系列之-项目介绍
- 自己动手写一个轻量级的Android网络请求框架
- 介绍一个Android开源项目:GifView——Android显示GIF动画
- 自己动手写一个轻量级的Android网络请求框架
- 自己开发了一个小框架,介绍一下
- Android RocooFix热修复动态加载框架介绍
- 来,咱们自己写一个Android的IOC框架!
- 开源自己的一个小android项目(美女撕衣服游戏)
- android ui定义自己的dialog(项目框架搭建时就写好,之后事半功倍)
- Android面试一天一题(2)优雅地介绍自己的项目
- android 一个应用去获取另一个应用assets下面的资源通过框架代码桥梁------项目实战成功案例
- 一个Android项目中各目录介绍
- android ui定义自己的dialog(项目框架搭建时就写好,之后事半功倍)