ios WaxPatch热更新原理

以下是引用他人文章内容:

  • 为什么需要 WaxPatch

    很多情况下,已经在 AppStore 上线的应用需要紧急缺陷修复,此时便需要使用某些技术手段,使应用程序能够动态下载补丁,进行缺陷修复。
  • 什么是 WaxPatch

    迄今为止,脚本语言中运行速度最快的是 Lua。Lua 语言由巴西里约热内卢天主教大学的 Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo 于 1993 年开发的。其最初的设计目的是提供一个方便嵌入到应用程序中得脚本语言。Lua 语言完全使用 ANSI C 实现,其设计精巧,代码优美。Lua 的解释器总共在 200k 大小,而且运行速度大约是 C 语言的 1/5,语法比较简单,即使不是专业的编程人员也容易掌握。
    2003 年,随着暴雪的大型在线网络游戏 《魔兽世界》的发布,Lua 逐渐被人们所知(《魔兽世界》的插件系统就是使用 Lua 开发), Lua 逐渐在游戏界流行起来。现在国内几乎大部分游戏策划都使用 Lua 语言来进行数值或者关卡的设计。

    《魔兽世界》内的Lua编辑器

由于 Lua 编程简单,运行速度快,在 iOS 上, 一个支持使用 Lua 语言编写 iOS 应用的项目 Wax 诞生了。Wax 项目允许用户使用 Lua 语言调动苹果 iOS SDK 的功能,进行应用程序的开发。

Wax Patch 项目是由 Wax 项目衍生而来,Wax patch 不仅仅允许用户使用 Lua 调用 iOS SDK 和应用程序内部的 API, 而且使用了 Objective-C runtime 的 class_replaceMethod 调用替换应用程序内部由 Objective-C 编写的类方法,从而达到功能微调或者缺陷修复的目的。

Wax/WaxPatch 主要特点:

● 所有 Objective-C 调用接口构建在 Objective-C runtime 之上,所以其调用 Objective-C 的 API 方式非常方便,不像调用 C/C++ 哪样,必须先为 Lua 编写调用接口(有些技术可以帮助 Lua 调用 C/C++ 编写的动态库而不必事先编写调用接口, 但是在 iOS 上不能调用应用程序自己编写的 API)。

● 对于 Objective-C 和 Lua 之间的数据类型转换进行了封装,使得开发者不必关心 Lua 和 Objective-C 的数据类型转换,方便开发。
WaxPatch 工作原理
Objectvie-C 语言的特性和实现机制决定了任何其他脚本语言对其进行调用都很方便。主要原因在于 Objective-C runtime 提供了对于 类/对象 等 OC 类型的反射和自省机制。
相关的 API 如下:

typedefstruct objc_class *Class;
structobjc_object "【"Class isa OBJC_ISA_AVAILABILITY;"】";
typedefstruct objc_object *id;
typedefstruct objc_selector *SEL;
typedefid (*IMP)(id, SEL, ...);
SELsel_getUid(const char *str);
constchar *object_getClassName(id obj);
Classobjc_getClass(const char *name);
Methodclass_getInstanceMethod(Class cls, SEL name);
Methodclass_getClassMethod(Class cls, SEL name);
IMPclass_getMethodImplementation(Class cls, SEL name);
IMPclass_replaceMethod(Class cls, SEL name, IMP imp, const char *types);

藉由以上 API,则可以通过字符串来动态调用 Objective-C 的类和对象的方法。

Wax/WaxPatch 调用 Objective-C 并不是简单得对 Objective-C runtime 的 API 进行 1 对 1 得封装,而是把所有的 Objective-C 的对象\类\函数\等抽象成一个 WaxInstance,对 WaxInstance 进行操作。而 WaxPatch 则对 WaxInstance 的元表的 __newindex 属性进行改写,调用 class_replaceMethod 方法改写父类的函数实现,使用 forwardInvocation 机制把针对父类的调用方法转发到 Lua 改写的类方法里面。
动态补丁流程
我们在一些项目中使用 WaxPatch 来实现热更新机制,主要的流程如下所示。

1. 补丁包发布流程

2 客户端请求补丁流程

3 客户端使用补丁流程

整个流程遵循以下原则:

● 简单有效,避免复杂逻辑。整个补丁包是所有补丁的全量包而不是增量包。

● 安全性要有保证。发布版的补丁包是需要经过加密的,避免被恶意篡改。

● 正确性。在打补丁的过程中,一旦出现错误,则立刻退出补丁流程,避免对原应用程序的流程产生致命的损坏。

4 全量补丁包格式
├── 20150701_01
│ ├──LoadPatchViewController.lua
│ └──init.lua
├── 20150703_01
│ ├──LTMoviePlayerViewController.lua
│ ├──LTPlayControlCenterView.lua
│ └──init.lua
├── LuaPatchManager.lua
└── letv_hotpatch_mapping.lua

① letvPatchManager.lua :补丁管理和执行文件,通过对客户端版本号和 letv_hotpatch_mapping.ua 文件判断补丁是否应该用于客户端。
② letv_hotpatch_mapping.lua:补丁索引文件,记录补丁适用于那个客户端版本。
③ 20150701_01:补丁包分包,为了方便补丁包管理,对单个补丁文件进行分组。
④ 20150701_01/init.lua:补丁分组执行文件。
⑤ 20150701_01/xxxx.lua:功能性的补丁。
整个方案主要由以下部分组成:

● 补丁包管理器:集成在客户端内部,使用 Objective-C 编写,负责从服务器下载补丁包,并解压到客户端的沙盒中。

● 补丁包:见上文。

● 补丁打包器:负责把所有明文补丁进行加密,并打包成 zip 格式供客户端下载。
改进WaxPatch
block 调用和实现
WaxPatch 对于 Objective-C 的 block 支持不够完备,虽然有一些 WaxPatch 的衍生版本增加了一些 block 的支持,但是并不能令我们满意,尤其是 block 的参数支持上。对此。我们自己增加了 WaxPatch 对 block 的支持,做到了对 block 的可变参数的支持。

安全性解决方案
由于 WaxPatch 可以做到对所有 Objective-C 的 API 修改(包括系统的和客户端内部的)。所以理论上来说,一个非法的 lua 补丁可以修改客户端所有的流程和功能,以致于对最终用户的信息造成伤害。

为了保证客户端功能和流程的安全性,在发布的补丁包中,所有的 Lua 补丁源码都由秘钥进行加密。在客户端方面,我们针对 Lua 的解释器进行修改,使用公钥进行解密和验证码,避免非法的 Lua 补丁文件被执行。
其他解决方案与结论
与 WaxPatch 方案相同的另外一个方案是 JSPatch。JSPatch 使用系统内置的 Javascript 解释器来动态 Javascript 代码,达到与 WaxPatch 同样的目的。其原理与 WaxPatch 基本相同。

经过调查,JSPatch 与 WaxPatch 相比,有一些固有的缺点无法解决:

① 在 iOS6.0 系统上,Apple 并没有开放 JavascriptCore 引擎,需要自己内置 JS 引擎,增加客户端的体积。

② 由于 JSPatch 使用系统的 JavascriptCore 引擎,我们无法去验证 Javascript 补丁的合法性和有效性,对客户端带来了很大的安全隐患。

以上原因决定使用 WaxPatch 的方案而不是 JSPatch 的方案。

软件开发的正途应该是:以加强代码质量和严格的测试来控制客户端质量。虽然 WaxPatch 可以做到对线上应用程序的缺陷进行快速修复,但是这种手段永远只能作为最后的一个防线,而不能过于依赖它。

附上开源项目

https://raw.github.com/mmin18/Create-a-More-Flexible-App/master/Wax
https://github.com/mmin18/WaxPatch

时间: 2024-10-01 03:45:36

ios WaxPatch热更新原理的相关文章

Webpack热更新原理

开发环境页面热更新早已是主流,常见的需求如赛事网页推送比赛结果.网页实时展示投票或点赞数据.在线评论或弹幕.在线聊天室等,都需要借助热更新功能,才能达到实时的端对端的极致体验. webpack-hot-middleware webpack-hot-middleware中间件是webpack的一个plugin,通常结合webpack-dev-middleware一起使用.借助它可以实现浏览器的无刷新更新(热更新),即webpack里的HMR(Hot Module Replacement).如何配置

react native ios版本热更新

react native 热更新的好处 js脚本代码改变了,比如对ui进行了一些修改,客户端要是想更新的话,如果直接下载apk 或者ipa,一个是浪费流量,还有比较麻烦 热更新只要下载打包好的bundle 文件,然后进行替换就可以了 思路比较简单,客户端跟服务端都维持 一个bundle版本信息,如果服务端的版本比客户端的 版本新就下载,然后替换掉 重新渲染就OK了 具体实现,如果没有 热更新,载入bundle的代码是这样的 jsCodeLocation = [[RCTBundleURLProvi

python基于函数替换的热更新原理介绍

热更新即在不重启进程或者不离开Python interpreter的情况下使得被编辑之后的python源码能够直接生效并按照预期被执行新代码.平常开发中,热更能极大提高程序开发和调试的效率,在修复线上bug中更是扮演重要的角色.但是要想实现一个理想可靠的热更模块又非常的困难. 1.基于reload reload作为python官方提供的module更新方式,有一定作用,但是很大程度上并不能满足热更的需求. 先来看一下下面的问题: >>> import sys, math >>

webpack基本概念、打包流程和热更新原理

webpack基本概念 1. webpack中的module,chunk 和 bundle module 就是一个js模块,就是被require或export的模块,例如 ES模块,commonjs模块,AMD模块chunk 是 代码块,是进行依赖分析的时候,代码分割出来的代码块,包括一个或多个module,是被分组了的module集合,code spliting之后的就是chunkbundle 是 文件,最终打包出来的文件,通常一个bundle对应一个chunk 2. webpack中load

ios wax热更新之安装wax(xcode7.3.1)

通过Finder浏览到你保存该项目的文件夹.创建三个新的文件夹:wax.scripts和Classes. 第一:首先,下载源代码的压缩包.Wax放在GitHub上(https://github.com/probablycorey/wax) 第二:现在,执行下列操作: ◆ 拷贝lib和bin文件夹,把它们粘贴到位于WaxApplication项目文件夹里面的wax文件夹.打开WaxApplication项目文件夹里面的wax/lib/extensions/文件夹.删除SQLite和xml文件夹,

移动端热更新方案(iOS+Android)

PPT资源包含iOS+Android 各种方案分析:https://github.com/qiyer/Share/blob/master/%E7%83%AD%E6%9B%B4%E6%96%B0%E5%88%86%E4%BA%ABPPT.pptx 一 .热更新(热修复)产品背景 这里谈到的热更新都是指APP(不包含网页).APP按大类别可以粗略分为 应用 和 游戏.APP的开发周期是极其快速的,在实际开发流程中,我们总会有一些需求迫使我们短时间内快速上线,比如需求流程出错,程序员主观导致的一些bu

iOS热更新的几种方案

iOS APP的上架审核一直是个令人困扰的问题,动辄一个星期甚至半个月的审核时间,往往会耽误产品的运营计划. 尤其是,审核过程中难以避免的会被苹果拒绝,然后又是一个周期,很是痛苦. 除了在提交审核前,尽可能的保证产品没有Bug,以及充分研究苹果的app审核政策外,从技术开发层面如果能解决热更新问题,则再好不过了. 所以我简单整理了以下一些技术,可用于产品的内部更新,而不用重新提交给苹果审核.如果有更多的方案,或是错误,也请提出. 1. Hybrid App 混合架构,借助于Html,JS等前端技

ios app 实现热更新(无需发新版本号实现app加入新功能)

眼下可以实现热更新的方法,总结起来有下面三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的ios应用 ios app能够在执行时从server拉取最新的js文件到本地.然后执行,由于js是一门动态的 脚本语言.所以可以在执行时直接读取js文件执行,也因此可以实现ios的热更新 2. 使用lua 脚本.lua脚本如同js 一样,也能在动态时被.之前愤慨的小鸟使用 lua脚本做的一个插件 wax,能够实现使用lua写ios应用.热更新时,从server拉去

ios app 实现热更新(无需发新版本实现app添加新功能)

目前能够实现热更新的方法,总结起来有以下三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的iOS应用 ios app可以在运行时从服务器拉取最新的js文件到本地,然后执行,因为js是一门动态的 脚本语言,所以可以在运行时直接读取js文件执行,也因此能够实现ios的热更新 2. 使用lua 脚本.lua脚本如同js 一样,也能在动态时被.之前愤怒的小鸟使用 lua脚本做的一个插件 wax,可以实现使用lua写ios应用.热更新时,从服务器拉去lua脚本