一、JIT(即时编译)的优势 (相较于AOT)
1、一次编译,到处运行
- AOT是直接将高级语言代码(例如C#、Java)编译为平台原生机器码,
- JIT则是先将高级语言代码编译为统一的中间码(IL / 字节码),然后拿着这份中间码文件跑 Windows/Android/Linux 等多数平台。

问题:为什么不直接省掉中间语言(IL),把C#(或java)本身当作那个"中间表示",让JIT直接编译C#代码?
核心原因是:C#是给人读写的"高级语言",而JIT需要的是给机器分析的"低级中间表示" 。**C# 语义太高级、复杂、抽象了,JIT "看不懂",**JIT如果直接编译C#,就必须设计复杂的逻辑算法来理解这种结构,会严重拉低性能,拖慢启动速度。
引入中间语言(IL),也带来了跨语言开发的能力,不管是C#、F#,还是VB等,任何语言只要编译成IL,就能共享同一个高性能JIT。
再次总结:AOT :必须针对每个平台、CPU 架构(arm64/armv7/x64)单独预编译,产出对应平台的原生二进制。
JIT :
嘿,兄弟,你只管用你最喜欢的语言(C#、F#、VB.NET随便挑),编译成中间语言(IL)丢给我就行。
你不用为每个平台准备一套编译工具,也不用记那些平台特有的坑。跨平台那堆破事------什么x86、x64、ARM,什么Windows、Linux、macOS------全交给我。
你生成的IL(中间语言),等程序跑起来,我看你代码在哪个平台上,就当场给你翻译成那个平台能跑的机器码。
别谢我,我叫JIT。你写逻辑,我跑世界。
2、能针对热点代码做激进优化,具备"自适应优化"能力
- JIT 可识别出频繁执行的"热点代码",然后针对性地优化。
- AOT 做不到这点:因为 AOT 不了解运行时的实际行为,只能按最通用的方式编译
3、支持"按需编译"
- **JIT 启动时不编译全部代码,**通常与解释器配合,先解释执行,只有热点代码才编译。这避免了编译所有代码(其中大部分可能永远不执行)的时间浪费。
- AOT 需要完整编译:即使某个函数在本次运行中从未被调用,AOT 也已经编译好了。对于大型应用(如微服务、CLI 工具),这会导致不必要的二进制体积增大和启动时间增加(虽然 AOT 整体启动快于纯 JIT,但按需编译的 JIT 首次执行到某段代码时不一定比 AOT 慢)。
JIT 和解释执行区别:
1、
JIT :将字节码编译成机器码 ,直接交给CPU执行。✅
解释执行 :不生成机器码,而是由解释器程序边读边模拟执行。❌一句话:
JIT = 把你的代码变成CPU的母语
解释执行 = 让翻译官用他的母语替你跑
2、
解释执行 :逐条翻译并立即执行,不保留翻译结果。
JIT 编译:将热点代码(频繁执行的代码)整体编译为机器码并缓存,后续直接执行。
维度 解释执行 JIT 编译 工作方式 边译边执行,用完即弃 编译后缓存机器码 启动速度 极快(无需编译) 较慢(需分析/编译热点) 执行速度 慢(重复翻译) 快(直接执行机器码) 典型场景 Python、Ruby、PHP Java、C#、现代JS引擎
苹果系统(特别是 iOS / iPadOS)明确禁止第三方 App 使用 JIT,但对解释执行没有限制。
为什么禁止 JIT?
核心原因是安全策略:
内存权限风险:JIT 需要在运行时动态生成机器码并写入可执行内存。这通常需要内存页同时拥有"可写"(W)和"可执行"(X)权限,会绕过现代操作系统的 W^X 保护机制,大大增加攻击面。
代码不可预判:JIT 编译出的代码是运行时动态生成的,苹果无法事先签名验证,也无法在出问题时远程撤销。
为什么允许解释执行?
解释执行不生成机器码:
逐条读取字节码并模拟执行,整个过程不涉及将新代码写入可执行内存
不触碰 W^X 安全机制,因此不受限制
二、虚拟机
关于CLR (公共语言运行时):
- 在微软**.NET 平台** ,实际处理中间代码的,是一个虚拟机 ( CLR (公共语言运行时))而 不只是一个JIT,JIT 是在CLR中 负责"编译 "这一重要环节,CLR中除了JIT,还有 "垃圾回收器 (GC) " 、 " 类加载器 (Class Loader)" 等组成部分。

微软 .NET 是一个完整的开发生态平台 ,它包含 了 CLR ,而 CLR 内部又包含 了 JIT 作为它的核心执行引擎之一。
C# 语言 是 .NET 平台的主力语言 ,由微软在 2000 年发布,由 Anders Hejlsberg(他也是 Delphi 和 Turbo Pascal 的设计者)领导设计。
将 C# 语言编译为中间语言(CIL)的是 C# 编译器。这个编译器的可执行文件通常称为
csc.exe(C# Compiler 的缩写)。是 .NET 平台提供的核心工具之一。
关于Java虚拟机(JVM):
我们上面说的 CLR (公共语言运行时 ),实际上是属于微软**.NET** 框架的核心组成部分,我之所以也称为"虚拟机" , 是为了方便与 Java 虚拟机 (JVM) 归纳一类,微软的官方文档和技术社区更习惯直接使用 CLR 这个名字,而不是"虚拟机"这个泛称。日常语境中人们常说 ".NET CLR" 、" JVM " 的更多.。
1990s,JIT 成为 Java 实现"一次编写,到处运行"并兼顾高性能的关键,其虚拟机 JVM (HotSpot )因能智能检测"热点代码",并进行深度优化,成为经典。(2000s - 2010s) JIT 成为现代主流运行时的标配。微软在 .NET 平台实现 NET CLR、JIT。
对比:
| 概念 | Java 平台 | .NET 平台 |
|---|---|---|
| 源代码 | *.java 文件 |
*.cs (C#) 文件 |
| 编译器 | javac |
csc (C# 编译器) |
| 中间产物 | 字节码 (Bytecode) *.class |
CIL (公共中间语言) *.dll /*.exe |
| 虚拟机 | JVM (Java 虚拟机) | CLR (公共语言运行时) |
| 虚拟机内部 | 解释执行 / JIT 编译 | JIT 编译 (早期也有解释) |
| 运行时核心 | 垃圾回收 (GC)、安全沙箱 | 垃圾回收 (GC)、安全沙箱 |
Java 虚拟机(Java Virtual Machine,简称 JVM)是 Java 平台的基石 ,它是一个能够执行 Java 字节码的抽象计算机。正是 JVM 的存在,让 Java 程序能实现"一次编写,到处运行"(Write Once, Run Anywhere)的核心承诺。
三、Mono 虚拟机
2001年 Mono项目 由 Miguel de Icaza 发起,目标是在 Linux 上实现一个开源的 .NET 运行时。
2002-2014年 Mono 是 Linux、macOS、iOS、Android 等非 Windows 平台运行 .NET 程序唯一可行的选择。Unity 也是在早期就选择了 Mono 作为其游戏脚本运行时。
2016年2月 ,微软收购了Xamarin公司。由于 Xamarin 由 Mono 的原班人马创建并拥有 Mono 的版权,微软通过此次收购间接成为了 Mono 项目的管理者。
微软在 2019 年后停止了原版 Mono 的功能开发,但其核心代码已经被大量整合、重写并融入到现代的 .NET 运行时(CoreCLR) 中。
微软.Net CLR 曾是闭源的,Mono 是开源的。
Mono 虚拟机 和 微软.Net CLR ,是平起平坐的实现,而不是从属关系:
.NET 的核心部分------公共语言基础 ------在 2000 年就已被微软和英特尔提交给 ECMA(欧洲计算机制造商协会)进行标准化,成为了一个公开的国际标准:ECMA-335。
这套标准就像一份详尽的"施工图纸",公开定义了:
CIL 指令集(公共中间语言,即 .NET 的"字节码")
虚拟机的执行模型
核心类型系统
文件格式
因此,只要遵循这份公开的 ECMA-335 标准,任何组织或个人都可以从零开始,独立实现自己的 .NET 运行时。 Mono 正是这样做的。
当微软在 2014 年 终于开源了 .NET(特别是 .NET Core)的部分源代码后,Mono 的策略变成了:对于自己实现得不够好或不完整的部分(如 WCF、
System.Web),直接移植并使用微软开源的、性能更好的官方代码。Mono 、Unity 未来:
Unity 6.8 预计于 2026 年底正式发布, 从 Unity 6.8 开始,当你开发游戏时,编辑器后台将不再使用 Mono 运行时 。这意味着新版本的 Unity 编辑器本身将基于 CoreCLR 运行,从而享受更快的代码编译和热重载(告别"域重载"卡顿)。
Mono作为脚本后端 (Scripting Backend):"保留但降级"
在构建(发布)游戏时,你依然会看到 Mono 选项,但它将不再是首要推荐。
现状:目前 Mono 是许多平台的默认后端 。
未来 :对于支持 JIT 的平台,官方推荐将转向性能更好的 CoreCLR 。Mono 将退居二线,主要作为一个"兼容性"选项保留。
在特定限制平台:"无法取代的 IL2CPP"
这里有一个容易混淆的点:Mono 后端的退出,不代表 Unity 会完全放弃现有的"非 CoreCLR"技术。
IL2CPP 依然坚挺 :对于 iOS、WebGL、游戏主机 等不允许或不适配 JIT 编译的平台,CoreCLR 无法直接工作 。
分工明确 :未来的格局将是:编辑器/开发阶段用 CoreCLR(快),发布到 PC/Mac 用 CoreCLR(性能好),发布到手机/主机用 IL2CPP(兼容/安全)。