Unity热更方案|热更原理|为什么要热更|CLR编译类型

为什么会有热更?

因为IOS平台限制了动态生成的代码的可执行权限,即禁止机器码写入进内存里(代码段)。也就变相的禁止了JIT编译方式。

编译过程 

开发语言编译为标准规范的IL语言(通用中间语言指令集),在目标平台上解释IL语言为目标平台特定的机器指令代码(所谓的native code)。有了IL语言,就跟具体的机器架构硬件无关了,因为只需要提供一个目标平台的CLR(CLR-运行时库)这个CLR根据当前平台解释编译IL语言即可生成目标平台特定的指令代码。换句话说 这些IL语言在真正要执行的时候会被加载进CLR中,也就是VM中,由VM通过JIT动态的编译成特定的机器指令代码然后执行。

步骤:第一次把多种语言编译为中间语言; 第二次把中间语言结合运行环境生成原生机器码,而在CLR的编译过程中又分为即时编译、静态编译及完全静态编译。

JIT

即时编译方式,在程序运行中,将CIL通用中间语言转换为目标平台的原生码(特定的机器指令代码)。

java虚拟机上jit技术是在代码第一次运行时进行编译,其后运行就不再进行编译了。现在所说的应该也是这种的。

AOT

提前编译方式,AOT编译是将程序源代码在编译时生成原生码。在程序运行时,不需要再进行编译,可以直接运行机器码,从而提高程序的运行效率。使用AOT编译的程序在运行中也会用到JIT,因为对于动态语言来说存在动态创建对象,执行代码的操作,比如我们通过读取一个配置文件去反射一个类。那么只有在执行代码引用类的时候才能知道具体反射的类。因为 AOT 编译只是根据代码来编译(比如代码中就直接体现出要反射的类名,或者泛型的具体类型,这些并不会动态生成代码的是可以通过预测来提前编译的),通过配置反射类编译器是无法预测到具体是哪些类。

Full-AOT

完全提前编译,完全静态,不允许动态生成代码,不允许动态创建类型,并不会动态生成代码的动态操作(如反射)是可以通过编译器的预测来提前编译。ISO平台下的编译方式是Full-AOT。

比如C# 由于.NET只能在Windows体系内运行,一公司开发了MONO,MONO提供了一套能够运行在各个平台下的CLR运行时。MONO版本的运行时也就是MONO VM(MONO虚拟机),其提供了即时编译器(JIT)、静态编译器、库加载器、垃圾回收器等功能。

早先的Unity跨平台方案是通过将各类语言编译为IL通用语言,再将通用语言放到Mono运行时中编译运行。

但MONO有着种种缺点。

  1. Mono VM在各个平台移植和维护非常耗时,有几个平台,就要实现几个目标平台的VM。所以针对不同的新平台,Unity就要把VM给移植一遍,同时还要保持维护。
  2. MONO的商业使用有一定限制,Unity和MONO在授权上存在一定的阻碍吧,Unity想要拿到新版本的MONO授权比较困难,这让高版本的C#的新特性无法使用,因为Unity的MONO没有适配高版本C#作更新,一直停留旧版本MONO。
  3. MONO VM是一个虚拟机,堆栈内存都在虚拟机里,IL语言在虚拟机中运行的。

IL2CPP

所以推出了IL2CPP,把编译后的IL再转成CPP,再由各个平台的C++编译器直接编译成能够执行的原生机器码。由于C++是一门静态语言,而像C#java这种动态语言是拥有动态特性的,如线程创建、泛型、反射、GC。所以还要引入一个IL2CPP VM,它负责处理和管理这些动态特性。

使用了IL2CPP了转换成静态语言了,代表所有东西都是提前编译完成的,编译方式只能是Full-AOT了。那就意味着不能在运行时动态生成代码,所以这就要求必须在编译时就完全确定需要用到的类型,所以在使用反射和动态特性的时候一定要注意这个操作会不会动态生成代码,编译器能否在编译时预测到。如果出错了,那就不只是ISO平台一个问题了,一不小心所有平台都会出错。有了IL2CPP,程序尺寸可以相对缩小,运行速度可以提高!
作者:Miracle
来源:麦瑞克博客
链接:https://www.unitymake.com/archives/unity/3740
本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议,转载请注明!
THE END
分享
打赏
海报
Unity热更方案|热更原理|为什么要热更|CLR编译类型
为什么会有热更? 因为IOS平台限制了动态生成的代码的可执行权限,即禁止机器码写入进内存里(代码段)。也就变相的禁止了JIT编译方式。 编译过程  将开发语……
<<上一篇
下一篇>>
文章目录
关闭
目 录