OCEval

需求

目前流行的 JSPatch/RN 基于JavaScriptCore提供了iOS的热修复和动态化方案。但是都必须通过下发Javascript脚本来调用Objective-C。 尤其是JSPatch,编写大量的JS代码来调用OC的方法,开发效率较低(目前可以借助语法转换器),运行效率也会打折扣。 更好的方案是直接编写Objective-C代码,来实现热修复或者动态化方案。开发效率更高,代码的执行效率也更高。

在python和javascript等脚本语言里,有类似eval()函数来直接动态执行代码。所以我实现了OCEval 这个库,让我们能直接动态执行Objective-C代码。例子如下:

NSString *inputStr = @"return 1 + 3 <= 4 && [NSString string] != nil;";
NSNumber *result = [OCEval eval:inputStr]; // result: @(YES)
复制代码

为了实现跟JSPatch类似的热修复功能,增加了方法替换。我们就可以通过下发Objective-C代码进行现有App的方法替换,来进行热修复的功能。

//在新的imp里直接调用旧的方法实现
NSString *viewDidLoad2 = @"{\
[originalInvocation invoke];\
";[OCEval hookClass:@"ViewController"selector:@"viewDidLoad"argNames:@[]isClass:NOimplementation:viewDidLoad2];
复制代码

OCEval甚至可以用来完整的编写一个页面或者App,并动态下发。我在iOS的Demo里实现了一个简单的页面,具体见源码。

实现原理

C和C++的性能高,是因为编译型语言在编译期就已经生成了机器码,运行时只需要执行机器码所以执行效率高,但是动态性差。 js的性能差,是因为js的runtime引擎通常是在实际执行前进行的编译的。优点是动态性好。 像Dart和python等等都可以编译打包执行或者JIT(Just in time)执行。

不同于C和C++,Objective-C是动态化的语言,Objective-C的runtime利用消息发送和转发可以动态地执行任何方法。 同时Objective-C又不同于javascript等完全动态化的语言。 因为大多数调用是在编译期就已经决定的,编译出可执行文件(mach-O)。

所以在OCEval里实现了一个轻量级的解释器,动态地解释Objective-C代码,同时利用OC的runtime消息转发来动态执行Objective-C的代码,就可以实现类似eval()函数的完全动态化方式。

解释器

Objective-C在LLVM下的编译过程:

源码 -> AST -> LLVM IR(中间语言) -> LLVM Bytecode -> ASM -> Native

LLVM的前端是Clang,Clang的工作是把源码变成AST语法生成树。

Clang的前端编译过程:

  • Preprocesser: 包括#include #import等预处理, #if,#ifdef 等条件,#define等宏定义
  • Lexer:词法分析,把文本变成token(Tokenizer)
  • Parser:语法分析,把token变成AST

但是在OCEval里,没有做得那么复杂,因为只是为了能够执行。所以只实现了词法分析和语法分析,得到语法生成树AST。

Runtime

执行的时候递归下降地执行每一条指令。这里利用的runtime主要是NSInvocation,利用methodSignature封装方法的调用惯例,跟JSPatch/RN的最终调用方式如出一辙。

+ (id)invokeWithCaller:(id)caller selectorName:(NSString *)selectorName argments:(NSArray *)arguments
{SEL selector = NSSelectorFromString(selectorName);NSInvocation *invocation;NSMethodSignature *methodSignature = [caller methodSignatureForSelector:selector];invocation= [NSInvocation invocationWithMethodSignature:methodSignature];[invocation setTarget:caller];[invocation setSelector:selector];NSUInteger numberOfArguments = methodSignature.numberOfArguments;NSInteger inputArguments = [arguments count];if (inputArguments > numberOfArguments - 2) {id result = invokeVariableParameterMethod(arguments, methodSignature, caller, selector); //转而调用objc_msgsendreturn result;}return [self invokeWithInvocation:invocation argments:arguments];
}
复制代码

参考JSPatch,在类似[NSString stringWithFormat:]这样可变参数的方法里使用objc_msgsend。因为NSInvocation不支持不确定的参数个数的情况。

性能

因为省去了跟JavascriptCore进行参数传递的过程,单个方法调用比JSPatch/RN快100%,耗时只有JSPatch一半,多个方法调用优势更大,耗时可能只有30%以下。

NSInvocation的调用跟Native速度差不多。但是因为动态调用很麻烦,入参出参和调用惯例都需要动态定义,同时上下文参数在内存的传递也比较慢,所以整体是比原生慢很多(动态化必要的牺牲)。

审核

我没有尝试过提交AppStore审核,但是鉴于JSPatch屡次被拒绝,被拒绝的可能性极大。我们的App确实也没有热修复的需求。

感谢

感谢JSPatch,libff,Aspect

Github 链接在 OCEval

转载于:https://juejin.im/post/5c24a8396fb9a049d5198dfc

OCEval-动态执行ObjectiveC的热修复方案相关推荐

  1. bat比较有意思的代码_腾讯开源的 Unity全系列 代码逻辑热修复方案--InjectFix

    InjectFix 腾讯开源的 Unity 代码逻辑热修复方案 Unity代码逻辑热修复 可用于Unity业务的bug修复,支持Unity全系列,全平台. 几个亮点 直接在Unity工程上修改C#即可 ...

  2. Android App 线上热修复方案

    热修复一词恐怕最早应用在微软.为了巩固其windows系统和office的市场占有率,微软开发并维护了一套线上修复方案,用于修复漏洞及特定问题(LDR),避免延续到发版解决(GDR),详见HotFix ...

  3. Robust热修复方案实现原理

    前言 本文旨在通过分析源码一步步分析Robust热修复的实现原理,前半部分首先分析一下Robust思路中运用到的技术方案:后半部分多为源码部分,即Robust对于技术方案的实现与运用. 1.关于Rob ...

  4. Android 热修复方案Tinker(五) SO补丁加载

    基于Tinker V1.7.5 Android 热修复方案Tinker(一) Application改造 Android 热修复方案Tinker(二) 补丁加载流程 Android 热修复方案Tink ...

  5. android热修复方案

    热补丁方案有很多,其中比较出名的有腾讯Tinker.阿里的AndFix.美团的Robust以及QZone的超级补丁方案.他们的优劣如下: 一.Tinker 热修复 Tinker通过 Dexdiff 算 ...

  6. Android App 线上热修复方案Xposed

    热修复一词恐怕最早应用在微软.为了巩固其windows系统和office的市场占有率,微软开发并维护了一套线上修复方案,用于修复漏洞及特定问题(LDR),避免延续到发版解决(GDR),详见HotFix ...

  7. JAndFix: 基于Java实现的Android实时热修复方案

    简述 JAndFix是一种基于Java实现的Android实时热修复方案,它并不需要重新启动就能生效.JAndFix是在AndFix的基础上改进实现,AndFix主要是通过jni实现对method(A ...

  8. android 热修复 需要重启应用嘛?_Android热修复方案盘点

    前言 上一个大的系列文章叫 "手把手讲解", 历时10个月,出产博文二十余篇,讲解细致,几乎每一篇都提供了详实的原理讲解,提供了可运行 githubDemo,并且针对Demo中的关 ...

  9. 干货满满,Android热修复方案介绍

    摘要:在云栖社区技术直播中,阿里云客户端工程师李亚洲(毕言)从技术原理层面解析和比较了业界几大热修复方案,揭开了Qxxx方案.Instant Run以及阿里Sophix等热修复方案的神秘面纱,帮助大家 ...

  10. 常用热修复方案以及原理

    常用热修复方案以及原理 bsdiff.exe 比对文件不同 bspatch.exe 生成增量包 增量级别更新,应用很广泛,抖音微信都有使用增量更新 所有的热修复都是使用 反射和类加载机制完成热修复,和 ...

最新文章

  1. 网上找到一个用不同颜色显示表格奇偶行的例子
  2. 关闭mysql密码策略_MYSQL57密码策略修改
  3. java程序设计简明教程张晓龙_Java网络编程简明教程
  4. as3与php交互实现总结
  5. python编程入门指南-Python 入门指南
  6. 关于CUDA中cutil的一些问题
  7. ubuntu 卡死 安装 桌面_Ubuntu下图形界面卡死解决办法
  8. Mybatis知识点复习(第一次)
  9. matlab删掉txt文件中的数据,matlab中读取txt数据文件(txt文本文档)
  10. 计算机主机号怎么产看,怎么查看笔记本电脑出厂编号
  11. 面对传销,该怎么处理
  12. linux学习之用户管理篇
  13. PS抠发丝技巧 「选择并遮住…」
  14. 控制led亮度C语言程序,单片机pwm控制led亮度原理图
  15. android分辨率2k3k4k,android 不同分辨率适配
  16. 2022-2028全球及中国电动汽车充电站和充电桩行业研究及十四五规划分析报告
  17. 如何使用Redis实现电商系统的库存扣减?
  18. apache实验报告 linux_linux实验报告心得
  19. ncut算法分割图像的matlab,Ncut_9 归一化切割和图像分割算法及其论文, 不仅度量了不同分组之间总体不相似性, matlab 269万源代码下载- www.pudn.com...
  20. 【codeforces 794A】Bank Robbery

热门文章

  1. 【优化预测】基于matlab差分算法优化ANN预测【含Matlab源码 151期】
  2. php-openssl降级,openssl升级降级
  3. python svm向量_支持向量机(SVM)及其Python实现
  4. ai人工智能可以干什么_我们可以使人工智能更具道德性吗?
  5. yyyy-MM-dd HH:mm:ss和yyyy-MM-dd hh:mm:ss的区别
  6. Python创建二维数组
  7. flutter 判断是不是调试模式_Flutter之撸一个漂亮的登录界面的总结
  8. 用python画一只皮卡丘_用python画一只可爱的皮卡丘实例
  9. python 3维图形库_Python 绘制 3 维以上的高维图
  10. qt开发用的人多吗_新房认筹猫腻多!开发商只是为达到这个目的才认筹,你入坑了吗?...