大家好,我系苍王。

以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。

[Android]用架构师角度看插件化--章节列表


Replugin,为何我选择要研究这个的插件呢?很大的原因是因为它的介绍中说明,他只会有一个hook点。


一.Hook

hook点是什么?

我们入门Android的时候,一定会看到过这个图,但是你确定深刻了解到这个图的吗?

我们试着换着思维,用组件化的角度去看这张图,你会发现其层级依赖关系,与组件化的工程是非常类似的。(当然你看得角度不同,我只能说是类似)

倘若你用插件的思想来看,我们上层的众多应用(Applications)就是作为framewrok层的插件一样的存在。(Framework作为宿主一样的存在,只是它是对于应用们,他说了算,基于安全管理和效率,他能限制你们获取资源的权限和方法)

然后我们想要在独自的应用中做得像Framework层一样的加载应用,我们本身就享用了Framework层对资源等的加载机制。如果我们想要将某些资源加载,加载验证,权限限制等绕开,运用到手机本身Framework来完成,就会涉及到hook了。

以我理解:hook,当Framework运行时,拦截并替换掉Framework层中某些原生的方法或对象,让其运行到我们想要的效果。


滴滴的VirtualApk 会hook掉AMS(ActivityManagerService)和Instumentation,这两个Framework的文件非常重要,AMS是四大组件的入口,管理生命周期,管理应用通信等,Instumentation管理了Activity的生命周期的调用。有兴趣可以深入去看这两个Framework文件。而其他旧式插件化,还会hook掉一下Service,Broadcast的机制。

而Replugin却走的是完全和传统插件化不同的路,它hook掉的是ClassLoader,而且它只有唯一的hook点。


hook为何会不安全?

就是拦截和替换原生机制,因为Android的机型太多了,而且是开源的,那么各个厂商定制Rom的修改,不同版本的适配也是非常大的阻碍,倘若替换掉某些厂商修改Google原生Android的源码里面的方案,2️⃣刚好hook点没有兼容这方面的源码,就有引起hook失败或者崩溃的可能性。

意味着hook点越少,其可能产生修改的代码会变小,维护的代价会变小,耗损的人力资源就会变少,整个用户体验就会提升。

架构的标准,是要懂得,衡量 时间+空间+效率。唯一hook点,暂时Replugin应该是插件化hook点的极致了。



二.ClassLoader

对于Android 的ClassLoader,请认真仔细看下图,一张图为你解答各种疑问。

此图非常形象的说明Android里面ClassLoader的架构。

这里一般插件化框架,都是使用DexClassLoader动态加载dex文件。

DexClassLoader可以加载apk,dex,jar,还有zip后缀格式的文件,其最终应该是加载dex文件,这也是我QQ群中验证问题的答案。

BaseDexClassLoader,里面有一个DexPathList对象,是用来保存dex的列表的,而查询dex里面的资源、class都是在这个列表中遍历dex对象。

而Replugin是特别的其使用自定义的PathClassLoader来加载apk中的dex,其有别于其他插件框架。


三.唯一hook点

我们看一下Replugin的加载过程。

用的是官网的replugin-host-library为例子

Application中attachBaseContext是最快执行的,其调用了Replugin.App.attachBaseContext方法

他会调用到PMF这个类init方法,PMF是框架和住程序接口

其里面会调用pluginManger的初始化,还有PatchClassLoaderUtils.patch的方法。

PatchClassLoaderUitls这个类是修改宿主和私有属性的位置,其实就是那个唯一的hook点的位置

可以看到在patch中需要获取到整个application的context对象。

然后生成自己的classLoader对象,去hook掉mClassLoader对象,FieldUtils是对Java反射机制的封装,以后使用到发射的时候,可以参考一下这里的封装,感觉是迄今看到众多插件化的封装最完善的。

这里的对参数的说明很清晰,最终会返回RePluginClassLoader对象。

这里调用到RepluginClassLoader里面,copyFromOrginal会将一些需要更改的属性去掉final属性,才能开始修改。initMethods,反射来替换掉ClassLoader的方法

里面替换掉四个方法,findResource和findResources是资源的获取,findLibrary是库获取,getPackage就是获取包信息了。

这里MethodUtils是方法反射的封装,也是封装得非常好。

在Android源码中,是通过DexPathList中读取资源,Resource是以URL格式返回,而lib库是用String返回

包获取是在classLoader中完成的

这里你会发现有点矛盾的地方,因为有可能不是那么容易一下子能看明。

我们前面看到需要反射出一些BaseDexLoader的一些方法

但是你看到其继承调用的时候,却使用了一模一样的方法,这样不就用了一模一样的流程了?这有何意义?

这里其实意义就在于其传入的mOrig参数,这个参数是classLoader的对象,而不同插件间都有classloader,那么其分别调用插件间的classloader资源的时候,就需要在这里拦截调用。


以上就是对Replugin的唯一hook点的分析。

值得借鉴的地方。

(1)唯一hook点,是用hook掉足够大的ClassLoader对象,来让资源加载得到更加便利。

(2)Java反射机制的整合FieldUtils域反射封装和MethodUtils方法反射封装。


这里发一条广告,我创立了一个小密圈。

每天会分享java基础,组件化插件化相关,音视频开源项目分享。

最重要,带有群员们珍贵的分析和点评。

还有最新插件化框架的分析和运用,组件化架构技巧的分享,都尽在这里。

不需要一顿饭的价钱 ,68/一整年的学习资料。

付费是真干货,真正节省时间的通往技术的途径。

来到这里希望影响你的不只是技术提升,而且是人生的架构的导向。

成立两周已经有超过190+的小伙伴加入了我们的行列了,并且持续增加,让我们一起成长,群内还有不定时福利,包括原创书籍的福利哦。

我建立了一个关于Android架构学习的群,里面可以进一步进行组件化学习的交流。

群号是316556016,也可以扫码进群。我在这里期待你们的加入!!!

更多相关文章

  1. android listview为什么会执行很多次,频繁调用getview
  2. Android绘图机制(一)——自定义View的基础属性和方法
  3. Android中使用SAX对XMl文件进行解析
  4. Android仿搜狗浏览器加载动画
  5. Android优雅地处理按钮重复点击
  6. Android(安卓)ContentProvider数据共享全解析
  7. # Android的按键消息分发机制
  8. Android(安卓)性能监测工具,优化内存、卡顿、耗电、APK的方法
  9. Android中微信支付的调用方法

随机推荐

  1. 一线架构师的一些项目管理心得
  2. MySQL深入研究:快速安装MySQL
  3. 谈谈我在北理工博士分享会学习到的东西
  4. 结合HTTP 502-504 状态码学习Nginx配置
  5. spring cloud alibaba 组件版本关系
  6. 李飞飞老师离开谷歌?谣言而已
  7. 一次华为昇腾服务器OS部署过程
  8. 电脑本地改变IP如何实现??
  9. Linux下升级python3到python3.8
  10. html中节点的常用属性和方法