JIT编译器和CLR有什么不同?如果您将代码编译为il,并且CLR运行该代码,那么JIT在做什么?在CLR中添加泛型后,JIT编译发生了怎样的变化?
发布于 2009-03-02 12:16:08
JIT是CLR的一个方面。
具体地说,它负责将原始语言的编译器(例如,微软c#的csc.exe)生成的CIL (以下称为IL)更改为当前处理器原生的机器码(以及它在当前进程中公开的体系结构,例如32/64位)。如果有问题的程序集是ngen'd的,那么JIT进程是完全不必要的,CLR将在没有它的情况下很好地运行这段代码。
在使用尚未从中间表示转换的方法之前,JIT有责任对其进行转换。
JIT的确切生效时间是特定于实现的,并且可能会发生变化。然而,CLR设计要求JIT发生在相关代码执行之前,相比之下,JVM可以在单独的线程创建机器代码表示时自由解释代码一段时间。
“正常”CLR使用pre-JIT stub approach,其中by方法仅在使用时才进行即时编译。这涉及到让初始的本机方法存根是间接的,以指示JIT编译该方法,然后修改原始调用以跳过初始存根。当前的精简版在加载类型时编译该类型上的所有方法。
来解决泛型的添加问题。
这是IL规范和JIT在语义方面的最后一次重大更改,而不是内部实现细节。
添加了几个新的IL指令,并为检测类型和成员提供了更多元数据选项。在IL级别也添加了约束。
当JIT编译具有泛型参数(显式或隐式地通过包含类)的方法时,它可能会为所使用的每种类型设置不同的代码路径(机器代码指令)。在实践中,JIT对所有引用类型使用一个共享实现,因为这些类型的变量将显示相同的语义并占用相同的空间(IntPtr.Size)。
每种值类型都将获得为其生成的特定代码,处理堆栈/堆上减少/增加的变量大小是一个主要原因。此外,通过在方法调用之前发出受约束的操作码,许多对非引用类型的调用不需要将值装箱即可调用该方法(这种优化也用于非泛型情况)。这还允许正确处理默认的<T>
行为,并在使用不可为空值类型时,将与null的比较剥离为无操作(始终为false)。
如果在运行时尝试通过反射创建泛型类型的实例,则运行时将验证类型参数以确保它们通过任何约束。这不会直接影响JIT,除非它在类型系统中使用(虽然可能性不大)。
发布于 2009-03-02 11:19:18
你将你的代码编译成IL,在运行时被执行并编译成机器码,这就是所谓的JIT。
编辑,以进一步充实答案(仍然过于简化):
当您在visual studio中编译C#代码时,它会转换为CLR能够理解的IL,该IL对于运行在CLR之上的所有语言都是相同的(这使得.NET运行时能够轻松地使用多种语言并在它们之间进行互操作)。
在运行时,IL被解释为机器码(特定于您所在的体系结构),然后执行。这个过程被称为即时编译,简称JIT。只有需要的IL才会被转换成机器码(而且只有一次,一旦编译成机器代码,它就会被“缓存”),在它被执行之前及时,因此得名JIT。
这就是C#的外观
C# Code
>
C#编译器>
IL>
.NET运行时>
即时编译器>
计算机代码>
执行
这是它在VB中的样子
VB Code
>
VB编译器>
IL>
.NET运行时>
即时编译器>
机器代码>
Execution
正如您所看到的,每种语言只有前两个步骤是唯一的,并且转换为IL后的所有内容都是相同的,这就是为什么您可以在.NET上运行几种不同的语言
发布于 2009-03-02 11:36:45
正如Jon Skeet所说,JIT是CLR的一部分。基本上,这是在幕后发生的事情:
现在,在执行以下命令时:
assembly.
https://stackoverflow.com/questions/601974
复制相似问题