Closed virjar closed 6 years ago
感谢作者,根据此思路实现,并测试通过,项目地址:https://gitee.com/virjar/xposedhooktool
这个实现的思路都大同小异,感谢反馈~ 虚拟机缓存可以杀死宿主来解决。
第一点真实不同系统的 你说的对,是需要一种更加通用的方案,但是第二点 我这种做法杀死宿主即可,因为zygote注入的只是我的框架,而在框架内部动态加载的dex, 所以只需要杀死宿主让这次的动态加载类缓存失效即可
哦,那没有歧义。我只说的是xposed插件入口缓存无法通过杀死宿主解决
hi,关于xposed插件更新后需要重启手机的原因我做了调查。大概跟了跟源码,发现是因为xposed在开机的时候注册钩子函数,同时加载了插件apk,然后使用的是pathclassloader。pathclassloader内部有一个机制,就会遇到加载的apk的时候,会将dex复制到/data/dalvik-cache,所以我们重装了软件,这个钩子函数对应的dex仍然在缓存里面。 另外一个问题是,同一个软件,如果是覆盖安装,她的apk路径会发生变化,其规则如下:
也就是说,及时不走缓存,因为新安装的apk的路径发生了改变,也会导致加载不到apk。这个原因是xposed是在系统启动的时候加载的插件apk,他就是使用这个路径注册到pathclassloader里面的,见代码
当插件代码重装,apk路径由 /data/app/com.virjar.xposedhooktool-1/base.apk变化为/data/app/com.virjar.xposedhooktool-2/base.apk,由于这个 PathClassLoader仍然持有对 /data/app/com.virjar.xposedhooktool-1/base.apk的引用,同时 /data/app/com.virjar.xposedhooktool-1/base.apk的副本存在于/data/dalvik-cahe,所以并不会加载新代码,同时旧代码也能够正常的被执行(没有真正删除)
为了实现热加载,我们需要做到的是在插件触发的时候,不去加载缓存,而走我们自己的类加载器加载。看你也有一个类似的实现,但是这个还可以做得更加通用,因为只要插件运行,证明手机里面存在一份最新代码,所以我们可以找到自己的位置,然后使用新的classloader去加载自己。如下:
原理就是,插件是有xposed创建的classloader加载的,那么插件的class能够得到对已经能够的classloader,进而得到xposed创建插件class的时候传入的apk路径。进而通过class得到插件自己第一次安装的时候的apk路径 /data/app/com.virjar.xposedhooktool-1/base.apk,基于这个路径,我们能够分析出packagename,然后我们注册context的attached回调,使用context加载插件的package,得到插件最新的安装路径。然后使用pathclassloader加载她。