---
title: "IL2CPP与IL2CPP VM"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/unity-il2cpp-vm/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/05-游戏图形与运行时/Unity/IL2CPP与IL2CPP VM.md"
content_hash: 17f1ef11f0e801501bceda2a6e6f902f4cdbaf2e47cf8e6002a7c6a7dbe02452
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# IL2CPP与IL2CPP VM

> 创建时间：2020/6/4 17:46

IL to CPP : 把IL中间语言转换成CPP文件

## IL2CPP的出现意义

  1. Mono VM在各个平台移植，维护非常耗时，有时甚至不可能完成
Mono的跨平台是通过Mono VM实现的，有几个平台，就要实现几个VM，像Unity这样支持多平台的引擎，Mono官方的VM肯定是不能满足需求的。所以针对不同的新平台，Unity的项目组就要把VM给移植一遍，同时解决VM里面发现的bug。这非常耗时耗力。这些能移植的平台还好说，还有比如WebGL这样基于浏览器的平台。要让WebGL支持Mono的VM几乎是不可能的。

  2. Mono版本授权受限
大家有没有意识到Mono的版本已经更新到3.X了，但是在Unity中，C#的运行时版本一直停留在2.8，这也是Unity社区开发者抱怨的最多一 条：很多C#的新特性无法使用。这是因为Mono授权受限，导致Unity无法升级Mono。如果换做是IL2CPP，IL2CPP VM这套完全自己开发的组件，就解决了这个问题。

  3. 提高运行效率
根据官方的实验数据，换成IL2CPP以后，程序的运行效率有了1.5-2.0倍的提升。

  4. 可以利用现成的在各个平台的C++编译器对代码执行编译期优化，这样可以进一步减小最终游戏的尺寸并提高游戏运行速度。

## IL2CPP与Mono

Mono

![Mono编译运行结构](/media/9a65b2e77968472fddaa.png)

IL2CPP

![Alt text](/media/cec693ee1d57090abaf7.png)

在得到中间语言IL后，使用IL2CPP将他们重新变回C++代码，然后再由各个平台的C++编译器直接编译成能执行的原生汇编代码。

## IL2CPP VM

通过IL2CPP以后代码变成了静态的C++，但是内存管理这块还是遵循C#的方式，这也是为什么最后还要有一个 IL2CPP VM的原因：它负责提供诸如 **GC管理** ， **线程创建** 这类的服务性工作。但是由于去除了IL加载和动态解析的工作，使得IL2CPP VM可以做的很小，并且使得 **游戏载入时间缩短** 。

## AOT方式

由于C++是一门静态语言，这就意味着我们不能使用动态语言的那些酷炫特性。运行时生 成代码并执行肯定是不可能了。这就是Unity里面提到的所谓AOT（Ahead Of Time，运行前编译）编译而非JIT（Just In Time）编译。其实很多平台出于安全的考虑是不允许JIT的，大家最熟悉的有iOS平台，在Console游戏机上，不管是微软的Xbox360， XboxOne，还是Sony的PS3，PS4，PSV，没有一个是允许JIT的。使用了IL2CPP，就完全是AOT方式了，如果原来使用了动态特性的 代码肯定会编译失败。这些代码在编译iOS平台的时候天生也会失败，所以如果你是为iOS开发的游戏代码，就不用担心了。因此就这点而言，我们开发上几乎 不会感到什么问题。

### JIT优点：

可以根据当前硬件情况实时编译生成最优机器指令（ps. AOT也可以做到，在用户使用是使用字节码根据机器情况在做一次编译）
可以根据当前程序的运行情况生成最优的机器指令序列
当程序需要支持动态链接时，只能使用JIT
可以根据进程中内存的实际情况调整代码，使内存能够更充分的利用

### JIT缺点：

编译需要占用运行时资源，会导致进程卡顿
由于编译时间需要占用运行时间，对于某些代码的编译优化不能完全支持，需要在程序流畅和编译时间之间做权衡
在编译准备和识别频繁使用的方法需要占用时间，使得初始编译不能达到最高性能

### AOT优点：

在程序运行前编译，可以避免在运行时的编译性能消耗和内存消耗
可以在程序运行初期就达到最高性能
可以显著的加快程序的启动

### AOT缺点：

在程序运行前编译会使程序安装的时间增加
牺牲Java的一致性
将提前编译的内容保存会占用更多的外

## 其他资料

<https://zhuanlan.zhihu.com/indieace>
IL2CPP怎么用：<https://zhuanlan.zhihu.com/p/19972666>
IL2CPP深入讲解：
<https://zhuanlan.zhihu.com/p/20063880>
<https://zhuanlan.zhihu.com/p/20207712>

## 参考文献

<https://zhuanlan.zhihu.com/p/19972689>
via IndieACE

<https://www.cnblogs.com/linghu-java/p/10577515.html>
