背景
2017年JSPatch相关App都会收到警告邮件,提示删除相关SDK
Apple之所以能揪出JSPatch,则是因为JSPatch中涉及使用到dlopen(),dlsym(),responsToSelector :、 performSelector:,method_exchangeImplementations()等方法。但实际上我们的项目中也存在上述几个方法,依然能过审。所以推测被卡住的原因与这几个方法相关,但不必然相关。
PS:已确认dlsym()函数会触发苹果的监测,造成上线失败。
现在如果引入JSPatch仍然会有被拒的风险,以下是官方的原话:
JSPatch 平台使用公告(2019.1.30)
平台最新 SDK 1.8.2 处于试验阶段,未能确保审核通过,有意配合试验者可邮件获取 SDK。
SDK 1.8.0 版本有较大概率审核被拒,但企业版APP可用,若确认使用可点此下载用平台最新的 SDK 接入可以通过审核吗
可以通过,已有接入并通过审核的 APP。
为什么平台 SDK 能通过审核
因为做了简单的类名修改混淆。
为什么游戏中允许热更新呢?
游戏中的热更新技术主要的实现方式是把动态脚本下载之后,让动态脚本调用游戏引擎提供的接口实现缺陷修复。与 JSPatch不同的是,动态脚本并不能任意调用全部原生代码,而是只能根据游戏引擎提供的接口调用相关功能。在这个过程中,游戏引擎的原生端作为一个安全沙箱,提供了一个安全的保护层,只要游戏引擎不要对外提供获取通讯录的接口,黑客就无法通过替换动态脚本的方式获取用户的隐私资料。进而可以被认为是安全的,自然就不在苹果的禁止范围内。
解读规范
2015 年苹果发过一篇协议《Apple Developer Program License Agreement》,文中第 3.3.2 节有一段关于热更新的内容:
Except as set forth in the next paragraph, an Application may not download or install executable code. Interpreted code may only be used in an Application if all scripts, code and interpreters are packaged in the Application and not downloaded. The only exceptions to the foregoing are scripts and code downloaded and run by Apple's built-in WebKit framework or JavascriptCore, provided that such scripts and code do not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store.
这一段话大概就是说除了 Webkit 和 JavascriptCore 可以动态执行下发的脚本和文件,其它所有脚本/代码/解释器都必须打包在 APP 内部。这句话其实就给 React Native 留了一个口子:React Native 就是用 JavascriptCore 执行 JS 脚本文件的,那么动态下发也是合理的。
Interpreted code may be downloaded to an Application but only so long as such code: (a) does not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store, (b) does not create a store or storefront for other code or applications, and (c) does not bypass signing, sandbox, or other security features of the OS.
这一段话大概就是说,我允许你热更新,但是必须遵循我这三条规定:
- 不能大的修改 APP 功能,导致应用实际功能和 APP Store 的宣传不符
- 不能动态创建应用商店
- 不能绕过签名/沙箱/OS 的安全功能
现在市面上的热更新方案:
一、阿里百川hotfix、Sophix、LuaView,腾讯的Bugly、OCS,滴滴的DynamicCocoa。
- 阿里百川hotfix、Sophix,仅支持安卓
- LuaView,类似于Flutter,将Android、iOS原生的UI、网络、存储、硬件控制等能力桥接到Lua层,进行动态下发
- Bugly内部集成的JSPatch支持的热更新
- OCS是全新设计的iOS动态化方案。我们定义了一套精确描述OC语义的字节码指令集(OCScript),开发了一套全自动编译器(OCSCompiler),实现了一个高性能的虚拟机(OCSVM)以及一个可以跟底层无缝对接的桥接器(OCSBridge)。我们首先使用OCS编译器把OC源码转化成OCS字节码,然后通过OCS桥接器实现OCS虚拟机与Native运行时的互联,最后使用OCS虚拟机对OCS字节码进行解释运算,并驱动Native运行时完成逻辑的执行,以此达到Native代码动态化的效果。OCS被用于iOS APP安装包减包、功能插件化、HotPatch等方方面面动态化需求。
- DynamicCocoa 闭源
二、Weex、RN、Hybrid
本身由js编写的代码,自然可以进行js进行bundle拉取
三、TTPatch、MangoFix
1.TTPatch
https://github.com/yangyangFeng/TTPatch
(star:420)
TTPatch2.0,核心实现替换为libffi实现.同时将代码重构,修改敏感命名.TTPatch更新为TTDFKit
官方风险提示: 仅供技术交流使用,上架有风险!!!!
2.MangoFix
https://github.com/YPLiang19/Mango
(star:890)
是DSL即 “领域专用语言”,用的是解析器进行词法、语法、语义检查和分析,作者用到了libffi库(用于高级语言之间的相互调用)进行运行时动态创建C函数,然后在创建的C函数中查找MangoFix脚本中方法并调用(这个用了类似dlsym的symdl进行动态调用函数),然后用刚刚创建的C函数替换原来Method的IMP指针并保留原有的IMP指针
脚本和OC极度类似,接入和jspatch相似,有一个下发脚本的接口,缺点就是下发完脚本需要重新进入页面才能更新
参考资料: