App热更新技术——JSPatch学习分享

如果不清楚本文的主角 JSPatch是什么请看我博客中的JSPatch学习笔记: 这里这里

背景

iOS Developer Program License Agreement里3.3.2提到不可动态下发可执行代码,但通过苹果JavaScriptCore.framework或WebKit执行的代码除外,JS正是通过JavaScriptCore.framework执行的。

基础原理

JSPatch 能做到通过 JS 调用和改写 OC 方法最根本的原因是 Objective-C 是动态语言,OC 上所有方法的调用/类的生成都通过 Objective-C Runtime 在运行时进行,我们可以通过类名/方法名反射得到相应的类和方法:

Class class = NSClassFromString("UIViewController");
id viewController = [[class alloc] init];
SEL selector = NSSelectorFromString("viewDidLoad");
[viewController performSelector:selector];

也可以替换某个类的方法为新的实现:

static void newViewDidLoad(id slf, SEL sel) {}
class_replaceMethod(class, selector, newViewDidLoad, @"");

还可以新注册一个类,为类添加方法:

Class cls = objc_allocateClassPair(superCls, "JPObject", 0);
objc_registerClassPair(cls);
class_addMethod(cls, selector, implement, typedesc);

理论上可以在运行时通过类名/方法名调用到任何 OC 方法,替换任何类的实现以及新增任意类。JSPatch 的基本原理就是:JS 传递字符串给 OC,OC 通过 Runtime 接口调用和替换 OC 方法。

JSPatch实现原理详解

Demo展示

demo地址

疑问:热修复都需要重启App后才能生效吗?

demo 中对以上疑问有实现,具体的原理理解下一节 方法替换

对demo代码的具体解释请看 这里

方法替换

OC上,每个类底层都是这样一个结构体:

struct objc_class {  
     Class isa;  
     Class super_class;    
     const char *name;   
     long version;  
     long info;   
     long instance_size;  
     struct objc_ivar_list *ivars;  
     struct objc_method_list **methodLists;  /*方法链表*/  
     struct objc_cache *cache;  
     struct objc_protocol_list *protocols;     
 }

其中 methodList 方法链表里存储的是 Method 类型:

typedef struct objc_method *Method;
typedef struct objc_ method {
  SEL method_name;
  char *method_types;
  IMP method_imp;
};

Method 保存了一个方法的全部信息,包括 SEL 方法名,type 各参数和返回值类型,IMP 该方法具体实现的函数指针。

通过 Selector 调用方法时,会从 methodList 链表里找到对应Method进行调用,这个 methodList 上的的元素是可以动态替换的,可以把某个 Selector 对应的函数指针IMP替换成新的,也可以拿到已有的某个 Selector 对应的函数指针IMP,让另一个 Selector 跟它对应,Runtime 提供了一些接口做这些事

JSPatch脚本文件下发加密

接入 JSPatch 时做 RSA 非对称加密传输


开发者自己在 APP 接入 JSPatch,若开发者没有针对传输的 JSPatch 脚本加密。攻击者就通过网络传输的中间人攻击手段下发恶意脚本到用户APP

动态更新方案对比:

JSPatch vs React Native

  1. 学习成本

    • React Native 是从 web 前端开发框架 React 延伸出来的解决方案,主要解决的问题是web页面在移动端性能低的问题。若使用React Native,就意味着iOS开发者需要学习web前端的一整套开发技能

    • JSPatch 是从终端开发出发的一种方案,JSPatch 写出来的代码风格与 OC 原生开发一致,加上一点 JS 语法的了解,就可以使用

  2. 接入成本

    • React Native 需要搭建一套开发环境,有很多依赖的库。React Native 是比较大的框架,据统计目前核心代码里 OC 和 JS 代码加起来有4w行,接入后安装包体积增大 1.8M 左右

    • JSPatch 是微型框架,只有 3 个文件 2k 行代码,接入后增大 100K 左右

  3. 开发效率

    • React Native 用近似 HTML+CSS 去绘制 UI,这方面开发效率相对 JSPatch 会高些,另外React Native 在开发效率上的另一个优势是支持跨平台,React Native 本意是复用逻辑层代码,UI 层根据不同平台写不同的代码

    • JSPatch 也可以借助 iOS 一些成熟的库去提高效率,例如使用 Massory。(尝试了其实也是相当吃力)

  4. 热更新能力

    • React Native 在热更新时无法使用事先没有做过桥接的原生组件

    • JSPatch 可以调用到任意已在项目里的组件,以及任意原生 framework 接口

方案对比表格:

学习成本 接入成本 热更新能力 开发效率 性能体验
JSPatch 中,不跨平台
React Native 高,跨平台

JSPatch vs Wax

对JSPatch的思考

  1. 进行热更新后下一个版本需要将JS代码修改为原生代码,不能停留超过一个版本。

  2. 编写JS脚本文件,调用OC原生的方法(方法名长得可怕)没有代码补全提示和高亮,显得非常吃力。

  3. 当要进行热修复的方法是一个代码量很大的方法,需要用JS重写这个方法,这会很痛苦。

新方案 : DynamicCocoa

优势所在:

  • 使用原生技术栈:使用者完全不用接触到 JS 或任何中间代码,保持原生的 Objective-C 开发、调试方式不变

  • 无需重写已有代码:已有 native 模块能很方便的变成动态化插件

  • 语法支持完备性高:支持绝大多数日常开发中用到的语法,不用担心这不支持那不支持

  • 支持 HotPatch:改完 bug 后直接从源码打出 patch,一站式解决动态化和热修复需求

  • 资源的支持,动态 bundle 支持:

    • xib 和 storyboard
    • xcassets
    • 不放在 xcassets 里的图片资源
    • 其他资源文件

DynamicCocoa:滴滴 iOS 动态化方案的诞生与起航

参考:http://blog.cnbang.net/tech/3237/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,462评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 关于HotfixPatch 在iOS开发领域,由于Apple严格的审核标准和低效率,iOS应用的发版速度极慢,稍微...
    whocare_阅读 1,740评论 0 11
  • 草根, 沾满了,黄的,红的,黑的泥土, 沿着曲曲弯弯的路, 把希望向远方延伸…… 没有自己精致的花园, 生不出孤傲...
    天山木兰阅读 193评论 0 0
  • 急转豪华大单间,永泰地铁站走路十分钟,或者搭便民车只需两分钟!二楼有活动中心,一楼超市,菜市场距离50米!房内储物...
    想租房阅读 133评论 0 0