我对JIT编译器的工作细节有点困惑。我知道C#会被编译成IL,第一次运行时就会被JIT编译。这是否涉及将其转换为本地代码?.NET运行时(作为虚拟机)是否与JIT编译后的代码交互?我知道这很幼稚,但我真的弄混了。我的印象一直是assemblies不会被.NET运行时解释,但我不明白交互的细节。
是的,JIT将IL代码转换为本地机器指令。
.NET运行时与JIT编译的本地机器代码进行交互,这意味着运行时拥有本地机器代码占用的内存块,调用本地机器代码等。
您说的正确,.NET运行时不会解释您的程序集中的IL代码。
当执行到一个尚未被JIT编译成本地机器码的函数或代码块(例如if块的else子句)时,JIT将被调用以将该IL块编译为本地机器码。完成后,程序执行进入新生成的机器代码以执行其程序逻辑。如果在执行该本地机器代码时达到尚未编译为机器代码的函数调用,则会即时调用JIT编译该函数。如此反复。
JIT不一定会立即将函数体的所有逻辑编译为机器代码。如果函数具有if语句,则if或else子句的语句块可能直到执行通过该块时才被JIT编译。未执行的代码路径仍保留为IL形式,直到执行它们。
编译的本地机器代码保存在内存中,以便在下次执行该代码段时再次使用。第二次调用函数时,它将比第一次调用更快,因为第二次不需要进行JIT步骤。
在桌面.NET中,本地机器代码将保存在应用程序域的生命周期内存中。在.NET CF中,如果应用程序的内存不足,本地机器代码可能会被丢弃。它将从原始IL代码重新JIT编译,并在下次执行经过该代码时再次使用。
代码被“编译”成类似汇编格式的 Microsoft Intermediate Language。
当您双击一个可执行文件时,Windows会加载 mscoree.dll
,该文件设置CLR环境并启动您的程序代码。JIT编译器开始读取程序中的MSIL代码,并将代码动态编译为x86指令,CPU可以执行。
public class Example
{
static void Main()
{
Console.WriteLine("Hey IL!!!");
}
}