Lua 热更

为什么选择 Lua 作为热更语言,为什么苹果不能JIT热更新?

https://xinzhuzi.github.io/2020/05/08/Unity/ToLua/ToLua%20%E4%BB%8B%E7%BB%8D/arrow-up-right

原理:当你运行程序之后,加载了原生代码(纯字符串)或者字节码(字符串转换的一种更容易被读取的字符串,一般是虚拟机的操作码)之后,经过了 JIT 编译器,生成了本平台下的一些原生的机器码,被放在了磁盘上,下次读取的时候,就不用再次经过 JIT 编译器编译过程了,会快速加载读取,但是原生代码不能被删除,此时是作为一种检测方式存在,此时的效率直追(C/C++效率)原生机器码; 没有经过 JIT 编译器,经过的是interpreter(解释器),逐条翻译的原生代码,此时的效率是达不到原生机器码的,所以很慢.

Lua 是基于寄存器实现的虚拟机,其他语言是基于栈实现的虚拟机

只有非越狱的iOS系统不能热更,因为 iOS 系统是不能加载没有被签名的代码/机器码,JIT 会生成机器码存放在磁盘上面,jit 可以在 iOS 上面创建机器码的内容保存在内存中,但是不能使用这些东西运行在 iOS 的 CPU 上面,就是因为没有签名.

JIT 这一点是涉及到内存可读可写可执行的权限,一般情况下内存肯定是可读的,iOS 系统的内存的执行权限就是那个签名.

热更的原理:将需要替换或者新增的二进制代码和资源加载到内存,然后运行它. 这种事情在windows上有很多方便的方式(例如dll)实现,而在Android虽然没有直接提供简单的方式仍然可以将动态链接库(so)当作数据读入到内存,然后执行之. 但是,作为没有越狱的iOS系统,苹果因为安全或者其他原因,启动了CPU的 No eXecute bit/edb/EVP(无执行位,即硬件防病毒技术) ,大致就是将 AppStore 审核过的代码加入签名文件,然后iOS运行app的时候会为 AppStore 审核过的代码开辟专用的内存空间,而其他app中的数据或者通过代码从线上下载的数据加载的时候会将存放的内存空间定义描述符定义为禁止运行,这样地址寄存器将不能够跳转到该空间,因此这部分代码不能运行. 这种安全技术应该在某些系统(比如安全要求很高的银行计算机)也是使用的的,不过一般我们接触到的电子产品也就只有iOS使用了这种技术. Lua是就将其翻译成对应的机器指令,逐条读入,逐条解释翻译.也就是通过软件cpu/虚拟机来执行这些代码,而虚拟机代码在提交的时候已经通过了AppStore之类的审核是可以被cpu执行的,你热更的Lua脚本只是一种数据,被虚拟机加载了而已,因此不会被No eXecute bit技术所限制.其实使用lua的主要原因是lua的字节码执行比较快,并且虚拟机运行比较稳定,维护足够好.同时lua模拟器足够轻量,几百 KB,还没有一张图片大,方便扩展. JIT: just in time 即时编译 编译器.使用即时编译器技术可以将翻译过的机器码保存起来,以备下次使用,因此从理论上来说,JIT 技术可以接近以前的纯编译技术. JIT 会判断当前的(一串)字节码是否经常调用,如果被经常调用,就直接编译为机器码,运行时,不用再去走字节码-->逐条翻译-->机器码这样的流程了,而是直接走 字节码-->机器码 这样的流程.而直接执行机器码在 iOS 上面是不被允许的.

最后更新于