Q1) 为什么 C# 最初编译为 IL,然后在运行时 JIT 编译并在虚拟机上运行(?)。还是 JIT 符合本机机器代码?
Q2)如果第二个为真(JIT 符合本机机器代码),那么代码运行的 .NET 沙箱在哪里?
Q3)另外,为什么首先将代码编译为IL。为什么不一直简单地编译为本机代码呢?MS 有一个名为 ngen 的工具,但为什么它是可选的?
Q1) 为什么 C# 最初编译为 IL,然后在运行时 JIT 编译并在虚拟机上运行(?)。还是 JIT 符合本机机器代码?
Q2)如果第二个为真(JIT 符合本机机器代码),那么代码运行的 .NET 沙箱在哪里?
Q3)另外,为什么首先将代码编译为IL。为什么不一直简单地编译为本机代码呢?MS 有一个名为 ngen 的工具,但为什么它是可选的?
IL 在进程运行时被 JIT(JIT = Just In Time)编译为本机机器代码。
使用虚拟机层允许 .NET 以一致的方式跨平台运行(例如,无论您是在 32 位还是 64 位机器上运行,int 始终为 32 位,而 C++ 并非如此)。
JIT 编译允许优化在代码运行时动态调整自身(例如,对频繁调用的代码位应用更积极的优化,或利用特定机器上可用的硬件指令,如 SSE2),这是您无法做到的静态编译器。
A1) JIT 编译为本机机器码
A2) 在 .net 中没有沙盒之类的术语。取而代之的是 AppDomains。它们作为 CLR 的一部分运行(即作为可执行进程的一部分)
A3) Jeffrey Richter 的 NGen 缺点:
NGen 的文件可能会不同步。当 CLR 加载 NGen 文件时,它会比较有关先前编译的代码和当前执行环境的许多特征。如果任何特征不匹配,则不能使用 NGen 文件,而是使用正常的 JIT 编译器过程。
加载时性能较差(变基/绑定)。程序集文件是标准的 Windows PE 文件,因此,每个文件都包含一个首选基地址。许多 Windows 开发人员都熟悉围绕基址和变基的问题。当 JIT 编译代码时,这些问题不是问题,因为正确的内存地址引用是在运行时计算的。
较差的执行时间性能。在编译代码时,NGen 无法像 JIT 编译器那样对执行环境做出尽可能多的假设。这会导致 NGen.exe 生成劣质代码。例如,NGen 不会优化某些 CPU 指令的使用;它为静态字段访问添加了间接访问,因为静态字段的实际地址直到运行时才知道。NGen 插入代码以在任何地方调用类构造函数,因为它不知道代码执行的顺序以及是否已经调用了类构造函数。
您可以使用NGEN创建 .NET 程序集的本机版本。这样做意味着 JIT 不必在运行时这样做。
.NET 先编译为 IL,然后编译为本机,因为 JIT 旨在针对当前运行代码的 CPU 优化 IL 代码。
.NET 代码被编译为 IL 以实现兼容性。由于您可以使用 C#、VB.NET 等创建代码,因此 JIT 需要一个通用指令集 (IL) 才能编译为本机代码。如果 JIT 必须了解语言,那么在发布新的 .NET 语言时需要更新 JIT。
我不确定沙盒问题,我最好的猜测是 .NET 应用程序与 3 个应用程序域一起运行。一个域包含 .NET 运行时(mscorlib、system.dll 等),另一个域包含您的 .NET 代码,我不记得另一个域的用途。查看http://my.safaribooksonline.com/9780321584090
1. C# 被编译为 CIL(或 IL),因为它与其他 .NET 语言共享一个平台(这就是为什么您可以用 C# 编写 DLL 并在 VB.NET 或 F# 中轻松使用它的原因)。然后CLR会将代码 JIT 编译为本机机器代码。
.NET 也可以在多个平台上运行(*NIX 和 OS X 上的 Mono)。如果 C# 编译为本机代码,这将不会那么容易。
2.没有沙箱。
3.包含在#1 的答案中
A1) 这样,它与平台无关(Windows、Linux、Mac),它还可以针对您当前的硬件使用特定的优化。当它被 JIT 编译为机器代码时。
A2) 整个框架(.NET 框架)都是沙盒,因此您可能通过您的应用程序进行的所有调用都将通过 .NET 框架沙盒。
A3) 与答案 1 一样,它允许 .NET 二进制文件在不同平台上工作,并在客户端机器上即时执行特定优化。
编译的 .Net 代码变成 IL,它是一种中间语言,与 Java 的目标代码完全相同。是的,可以使用NGen工具生成本机机器代码。NGen 将生成的本机映像绑定到机器,因此将 ngen 的二进制文件复制到不同的系统不会产生预期的结果。编译成中间代码允许运行时决策,否则不能(容易)用静态类型语言(如 C++)做出,它还允许代码在不同硬件架构上运行,因为代码在感觉它还以与位(例如 32 或 64)无关的方式描述了应该发生的事情的意图,而不是仅适用于 32 位系统或 64 位系统但不能同时适用于两者的机器特定代码。
此外,NGen 是可选的,因为正如我所说,它将二进制文件绑定到系统,当您需要编译机器代码的性能和动态类型语言的灵活性并且您知道二进制文件不会移动到一个不受约束的系统。