首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场

CLR与JIT
EN

Stack Overflow用户
提问于 2009-03-02 11:16:45
回答 7查看 31.7K关注 0票数 54

JIT编译器和CLR有什么不同?如果您将代码编译为il,并且CLR运行该代码,那么JIT在做什么?在CLR中添加泛型后,JIT编译发生了怎样的变化?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 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,除非它在类型系统中使用(虽然可能性不大)。

票数 54
EN

Stack Overflow用户

发布于 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上运行几种不同的语言

票数 83
EN

Stack Overflow用户

发布于 2009-03-02 11:36:45

正如Jon Skeet所说,JIT是CLR的一部分。基本上,这是在幕后发生的事情:

  1. 您的源代码被编译成一个字节代码,称为公共中间语言运行时,来自每个类和每个方法(以及所有其他内容:O)都包含在生成的可执行文件(无论是dll还是exe)的PE头中。
  2. 如果您正在生成可执行文件,则PE头还包括一个传统的引导程序,该引导程序负责在您执行可执行文件时加载

现在,在执行以下命令时:

assembly.

  • The

  • 现在,类有一个保存方法函数地址的矢量表,所以当你调用MyMethod时,这个表会被搜索,然后对地址进行相应的调用。

  • 现在,类有一个矢量表,它保存了方法函数的地址,所以当你调用MyMethod时,会搜索这个表,然后对地址进行相应的调用。在启动时,所有表的所有条目都具有JIT compiler.

  • When的地址,对其中一个方法进行调用,调用JIT而不是实际的方法并进行控制。然后,JIT将CIL代码编译成实际的汇编代码,用于适当的architecture.

  • Once。该代码被编译。JIT进入方法向量表,并将地址替换为编译的代码之一,因此,每次后续调用不再调用JIT.

  • Finally,,JIT处理对编译的代码的执行。

  • 如果你调用另一个尚未编译的方法,则返回到4...以此类推...
票数 31
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/601974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档