简单介绍下热修复,基于Xposed中的思想,通过修改c层的Method实例描述,来实现更改与之对应的java方法的行为,从而达到修复的目的。

Xposed:

诞生于XDA论坛,类似一个应用平台,不同的是其提供诸多系统级的应用。可实现许多神奇的功能。Xposed需要以越狱为前提,像是iOS中的cydia。Xposed可以修改任何程序的任何java方法(需root),github上提供了XposedInstaller,是一个android app。提供很多framework层,应用层级的程序。开发者可以为其开发一些系统或应用方面的插件,自定义android系统,它甚至可以做动态权限管理(XposedMods)。

Android系统启动与应用启动

Zygote进程是Android手机系统启动后,常驻的一个名为‘受精卵’的进程。

  • zygote的启动实现脚本在/init.rc文件中
  • 启动过程中执行的二进制文件在/system/bin/app_process

任何应用程序启动时,会从zygote进程fork出一个新的进程。并装载一些必要的class,invoke一些初始化方法。这其中包括像:

  • ActivityThread
  • ServiceThread
  • ApplicationPackageManager

应用启动中必要的类,触发必要的方法,比如:handleBindApplication,将此进程与对应的应用绑定的初始化方法;同时,会将zygote进程中的dalvik虚拟机实例复制一份,因此每个应用程序进程都有自己的dalvik虚拟机实例;会将已有Java运行时加载到进程中;会注册一些android核心类的jni方法到虚拟机中,支撑从c到java的启动过程。

Xposed做了手脚

Xposed在这个过程改写了app_process(源码在Xposed : a modified app_process binary),替换/system/bin/app_process这个二进制文件。然后做了两个事:

  1. 通过Xposed的hook技术,在上述过程中,对上面提到的那些加载的类的方法hook。
  2. 加载XposedBridge.jar

这时hook必要的方法是为了方便开发者为它开发插件,加载XposedBridge.jar是为动态hook提供了基础。在这个时候加载它意味着,所有的程序在启动时,都可以加载这个jar(因为上面提到的fork过程)。结合hook技术,从而达到了控制所有程序的所有方法。为获得/system/bin/目录的读写权限,因而需要以root为前提。

Xposed的hook思想

那么Xposed是怎么hook java方法的呢?要从XposedBridge看起,重点在XposedBridge.hookmethod(原方法的Member对象,含有新方法的XC_MethodHook对象);,这里会调到

private native synchronized static void hookMethodNative(Member method, Class<?> declaringClass, int slot, Object additionalInfo);

这个native的方法,通过这个方法,可以让所hook的方法,转向native层的一个c方法。如何做到?

When a transmit from java to native occurs, dvm sets up a native stack.
In dvmCallJNIMethod(), dvmPlatformInvoke is used to call the native method(signature in Method.insns).

在jni这个中间世界里,类型数据由jni表来沟通java和c的世界;方法由c++指针结合DVM*系(如dvmSlotToMethod,dvmDecodeIndirectRef等方法)的api方法,操作虚拟机,从而实现java方法与c方法的世界。那么hook的过程是这样:首先通过dexclassload来load所要hook的方法,分析类后,进c层,见代码XposedBridge_hookMethodNative方法,拿到要hook的Method类,然后通过dvmslotTomethod方法获取Method*指针,

Method* method = dvmSlotToMethod(declaredClass, slot);

declaredClass就是所hook方法所在的类,对应的jobject。slot是Method类中,描述此java对象在vm中的索引;那么通过这个方法,我们就获取了c层的Method指针,通过

SET_METHOD_FLAG(method, ACC_NATIVE);

将该方法标记为一个native方法,然后通过

method->nativeFunc = &hookedMethodCallback;

定向c层方法到hookedMethodCallback,这样当被hook的java方法执行时,就会调到c层的hookedMethodCallback方法。

通过meth->nativeFunc重定向MethodCallBridge到hookedMethodCallback这个方法上,控制这个c++指针是无视java的private的。另外,在method结构体中有

method->insns = (const u2*) hookInfo;

用insns指向替换成为的方法,以便hookedMethodCallback可以获取真正期望执行的java方法。现在所有被hook的方法,都指向了hookedMethodCallbackc方法中,然后在此方法中实现调用替换成为的java方法。

总结

回顾Xposed,以root为必要条件,在app_process加载XposedBidge.jar,从而实现有hook所有应用的所有方法的能力;而后续动态hook应用内的方法,其实只是load了从zypote进程复制出来的运行时的这个XposedBidge.jar,然后hook而已。因此,若在一个应用范围内的hook,root不是必须的,只是单纯的加载hook的实现方法,即可修改本应用的方法。

业界内也不乏通过「修改BaseDexClassLoader中的pathList,来动态加载dex」方式实现热修复。后者纯java实现,但需要hack类的优化流程,将打CLASS_ISPREVERIFIED标签的类,去除此标签,以解决类与类引用不在一个dex中的异常问题。这会放弃dex optimize对启动运行速度的优化。原则上,这对于方法数没有大到需要multidex的应用,损失更明显。而前者不触犯原有的优化流程,只检查需要hook的方法,更为纯粹、有效。

Android Xposed热修复原理简析相关推荐

  1. Android Handler与Looper原理简析

    一直感觉自己简直就是一个弱智,最近越来越感觉是这样了,真的希望自己有一天能够认同自己,认同自己. 本文转载于:https://juejin.im/post/59083d7fda2f60005d14ef ...

  2. Android热修复-Tinker简析

    一.简介 日常工作工作中难免会遇到项目上线后出现bug问题,如果紧急发版往往由于渠道审核时间问题,导致bug修复不及时,影响用户体验.这时我们需要引入热修复,免去发版审核烦恼. 热更新优势: 让应用能 ...

  3. Android Andfix热修复原理

    正常开发流程 热修复开发流程 当线上的项目出现问题了,需要重新发布版本解决bug,重新发新版本apk; 但是随着技术不断的更新,线上项目出现bug,可以通过热修复,在不需要发布新版本的情况下进行bug ...

  4. android中so文件格式详解,[原创]一 Android ELF系列:ELF文件格式简析到linker的链接so文件原理分析...

    Android ELF系列:ELF文件格式简析和linker的链接so文件原理分析 Android ELF系列:实现一个so文件加载器 Android ELF系列:手写一个so文件(包含两个导出函数) ...

  5. 【Android 热修复】热修复原理 ( 多 Dex 打包机制 | 多 Dex 支持 | Dex 分包设置 | 开发和产品风格设置 | 源码资源 )

    文章目录 一.Dex 打包设置 1.多 Dex 支持 2.Dex 分包设置 3.开发和产品风格设置 ( 非必须 ) 二.完整 build.gradle 配置 1.build.gradle 配置 2.d ...

  6. 【Android 热修复】热修复原理 ( 合并两个 Element[] dexElements | 自定义 Application 加载 Dex 设置 | 源码资源 )

    文章目录 一.合并两个 Element[] dexElements 二. 完整修复包加载工具类 三. 源码资源 一.合并两个 Element[] dexElements 在 [Android 热修复] ...

  7. 【Android 热修复】热修复原理 ( Dex 文件拷贝后续操作 | 外部存储空间权限申请 | 执行效果验证 | 源码资源 )

    文章目录 一.Dex 文件准备 二.外部存储空间权限申请 1.清单文件申请权限 2.动态申请权限 三.文件拷贝 1.文件拷贝 2.执行效果 四. 源码资源 一.Dex 文件准备 在 [Android ...

  8. 【Android 热修复】热修复原理 ( 修复包 Dex 文件准备 | Dex 优化为 Odex | Dex 文件拷贝 | 源码资源 )

    文章目录 一.修复包 Dex 文件准备 二.Odex 优化 三.Dex 文件拷贝 四. 源码资源 一.修复包 Dex 文件准备 异常代码 : 故意写一个异常代码 , 并执行该代码 , 肯定会崩溃 ; ...

  9. Android 热修复原理篇及几大方案比较

    热修复说白了就是"即时无感打补丁",比如你们公司上线一个app,用户反应有重大bug,需要紧急修复.2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也 ...

最新文章

  1. php数据库字段类型,mysql 字段类型说明
  2. python 基础 7.6 sys 模块
  3. android高仿微信UI点击头像显示大图片效果
  4. python安装第三方包总是超时_(python pip安装第三方库超时问题(raise ReadTimeoutErrorself._pool, None, 'Read timed out.')...
  5. 困了。还得背课文。变词型
  6. grafana授权公司内部邮箱登录 ldap配置
  7. 32位linux系统支持多大内存吗,linux32位操作系统支持大内存
  8. JavaScript高级程序设计学习(二)之基本概念
  9. requestmapping配置页面后_第004课:Spring Boot 项目属性配置
  10. spring接收ajax参数的几种方式
  11. 【割点】【割边】tarjan
  12. linux fdisk指定ext4,如何在Linux中创建新的Ext4文件系统(分区)
  13. 英语口语8级是这么炼成的!
  14. TFP-161/100/6MM/6MM/MPU在红尘里,靠近菩提
  15. 【BZOJ4484】【JSOI2015】最小表示(拓扑排序,bitset)
  16. C语言中将字符数字转换为数值的小技巧和方法
  17. 针对车载系统相关的功能分析(车载OS、芯片、导航、DC、总线系统等)
  18. 公众号文章阅读量数据导出
  19. isset与empty的区别
  20. 一池江水半江灯。繁星点点落江城,严霜寒雪封不住,若明若暗水火情

热门文章

  1. 用css做透明效果,CSS实现毛玻璃透明效果
  2. Blizzard(暴雪)公司的发迹史
  3. redis惰性删除 lazy free 源码剖析,干货满满
  4. T-SQL语言中局部变量(@)和全局变量(@@)
  5. 5g基站服务器需要芯片吗,5G基站为什么需要使用不一样的电源模块
  6. 误删除的图片怎么恢复?
  7. liquibase mysql_Liquibase的简单使用
  8. Saiku更改導出文件的文件名(十九)
  9. linux负载监控工具,理解 Linux 的平均负载和性能监控
  10. 2022年12月25日(星期天):骑行沙堤村