先说下AOT和JIT
JIT
JIT即:just in time,即时编译。正式点的定义:
一个程序在它运行的时候创建并且运行了全新的代码,而并非那些最初作为这个程序的一部分保存在硬盘上的固有的代码。就叫JIT。
要点:
- 程序要运行
- 会生成新的代码,与包内代码不同
- 运行创建的新代码
- ios封了内存(或者堆)的可执行权限,也就封了JIT
AOT
与JIT相反。
参考:
什么是跨平台?
简单来说就是写一套代码,一次编译,不需要修改任何代码,就可以在所支持的不同平台运行,不依赖操作系统,也不依赖硬件。
Unity如何实现跨平台
Unity的脚本处理有两种:
Mono
Mono是Xamarin提供的一个自由开放源码。Mono包括:C#编译器
和CIL虚拟机
及其他核心类库。
C#编译器(mcs)用来将C#代码编译成CIL(中间语言),CLI虚拟机的作用是将IL语言翻译成对应平台支持的原生码,IL的运行是依托于Mono虚拟机。
这样只需要不同平台拥有对应平台的Mono虚拟机,即可实现C#编译成的IL代码运行在对应的平台,这样Mono就实现了跨平台。
但是Mono有一些缺点,甚至是致命的缺点,如下:
- 运行效率较慢。
- Mono虚拟机移植困难,甚至某些平台无法移植,影响Unity的跨平台性。
- Unity与Mono的授权问题。
为了解决这些问题,unity推出了il2cpp的技术。在了解il2cpp之前先看下il、CIL、CLR之间的关系
。
IL,CIL,CLR 分别是什么
- IL: Intermediate Language,是一种属于通用语言架构和.NET框架的低阶的人类可读的编程语言。
- CIL: Common Intermediate Language,特指在.Net平台下的IL标准
- CLR: Common Language Runtime,通用语言运行时
通过上图可以看出:将**支持IL的语言(如C#)**的代码通过自己的编译器编译为 IL中间代码,最后统一由Mono虚拟机 执行IL代码。
IL2CPP
il2cpp
就是将上面生成的IL代码转换成C++
代码,然后通过不同平台的il2cpp虚拟机去编译执行转译好的C++
代码。
为什么需要有il2cpp VM(虚拟机)
这个东西呢?
那是C++本身是没这个东西的,C++
中本身也是不支持C#中的一些“骚操作”的,如:反射,GC,泛型,虚函数,接口,线程管理等,而这些就是il2cpp VM
要做的事情,而对于其他代码则是交给原生的c++
执行了。
il2cpp VM 如何实现的GC?
答:GC是一套垃圾回收算法。如:标记清除算法、分代收集算法等。unity中使用的是标记清除算法。只需要在il2cpp VM中实现一套GC算法使用即可。
il2cpp VM 如何实现的反射?
C++本身不支持反射。
在il2cpp编译过程中会根据反射过程调用的类型或方法信息分别转换为C++的结构体和函数信息,并生成一个中间文件。
在cpp执行过程中先读取中间文件获得类型信息和方法信息。然后直接使用这些信息或执行这些方法。
il2cpp 的缺点
- c# -> cpp不好调试,报错日志不清楚。
- AOT 不支持热更新。(但目前已有解决方案
HyBridCLR
)
HybridCLR的原理是:给il2cpp VM 提供一个特性,能够解释执行dll。