JIT(即时编译)、 AOT(预先编译)、虚拟机CLR 笔记

一、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?

核心原因是安全策略

  1. 内存权限风险:JIT 需要在运行时动态生成机器码并写入可执行内存。这通常需要内存页同时拥有"可写"(W)和"可执行"(X)权限,会绕过现代操作系统的 W^X 保护机制,大大增加攻击面。

  2. 代码不可预判: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 运行,从而享受更快的代码编译和热重载(告别"域重载"卡顿)。

  1. Mono作为脚本后端 (Scripting Backend):"保留但降级"

    在构建(发布)游戏时,你依然会看到 Mono 选项,但它将不再是首要推荐。

    • 现状:目前 Mono 是许多平台的默认后端 。

    • 未来 :对于支持 JIT 的平台,官方推荐将转向性能更好的 CoreCLR 。Mono 将退居二线,主要作为一个"兼容性"选项保留。

  2. 在特定限制平台:"无法取代的 IL2CPP"

    这里有一个容易混淆的点:Mono 后端的退出,不代表 Unity 会完全放弃现有的"非 CoreCLR"技术。

    • IL2CPP 依然坚挺 :对于 iOS、WebGL、游戏主机不允许或不适配 JIT 编译的平台,CoreCLR 无法直接工作 。

    • 分工明确 :未来的格局将是:编辑器/开发阶段用 CoreCLR(快),发布到 PC/Mac 用 CoreCLR(性能好),发布到手机/主机用 IL2CPP(兼容/安全)

相关推荐
NULL指向我2 小时前
Simplis仿真笔记1:Simplis_V8.4_x64安装过程
笔记
ouliten3 小时前
[Triton笔记6]层标准化
笔记
玄米乌龙茶1235 小时前
思维导图笔记:Prompt工程
笔记·prompt
zhangrelay6 小时前
ROS 2 Lyrical Luth启程-Ubuntu26.04-
linux·笔记·学习·ubuntu
Undergoer_TW6 小时前
SLAM实战避坑笔记:基础矩阵退化场景分析与解决方案
笔记·线性代数·矩阵
锦鲤52146 小时前
机器学习学习笔记
笔记·学习·机器学习
三品吉他手会点灯7 小时前
STM32F103 学习笔记-22-DMA(第1节)-DMA功能框图讲解和DMA初始化结构体讲解
笔记·stm32·单片机·嵌入式硬件·学习
咸甜适中7 小时前
rust语言学习笔记Trait(十一)Deref、DerefMut(解引用)
笔记·学习·rust
hj2862517 小时前
Linux存储空间管理完整笔记
linux·运维·笔记