当前位置:  开发笔记 > 编程语言 > 正文

CLR与JIT

如何解决《CLR与JIT》经验,为你挑选了5个好方法。

JIT编译器和CLR有什么区别?如果您将代码编译为il并且CLR运行该代码,那么JIT正在做什么?JIT编译如何通过向CLR添加泛型来改变?



1> thr..:

您将代码编译为IL,在运行时将其执行并编译为机器代码,这就是所谓的JIT.

编辑,更多地充实答案(仍然过于简化):

当您在Visual Studio中编译C#代码时,它变成了CLR理解的IL,IL对于在CLR之上运行的所有语言都是相同的(这使得.NET运行时能够使用多种语言和inter-op他们之间很容易).

在运行期间,IL被解释为机器代码(特定于您所在的体系结构),然后执行.此过程称为Just In Time编译或简称JIT.只有需要的IL被转换成机器代码(并且只有一次,它被编译成机器代码后被"缓存"),正好在它被执行之前,因此命名为JIT.

这就是C#的样子

C#代码>C#编译器>IL >.NET运行时>JIT编译器>机器代码>执行

这就是VB的样子

VB代码>VB编译器>IL >.NET运行时>JIT编译器>机器代码>执行

正如你所看到的那样,只有两个第一步对每种语言都是唯一的,并且在它变成IL之后的所有内容都是相同的,就像我之前所说的那样,你可以在.NET之上运行几种不同的语言.


-1用于将IL称为字节码,它是Java语义.IL(以前称MSIL)是正确的术语,不要混淆两者.改变这一点,你就得到了我的投票.
@fredrikholmstrom - 好,IL指令的大小是2个字节而不是单个字节.术语字节码不属于CLI.IL只缺少中间语言而且只是中间语言.

2> ShuggyCoUk..:

JIT是CLR的一个方面.

具体来说,它是负责将原始语言编译器(例如csc.exe for Microsoft c#)生成的CIL/MSIL(以下称为IL)更改为当前处理器本机的机器代码(以及它在当前进程中公开的体系结构)的部分,例如32/64bit).如果有问题的程序集是ngen'd那么JIT进程是完全没必要的,并且CLR将在没有它的情况下运行此代码.

在使用尚未从中间表示转换的方法之前,JIT有责任对其进行转换.JIT何时启动的
确切时间是特定于实现的,并且可能会发生变化.然而,CLR设计要求JIT 相关代码执行之前发生,相比之下,JVM可以自由地解释代码一段时间,而单独的线程创建机器代码表示.
"普通"CLR使用pre-JIT stub方法where方法是JIT编译时只使用它们.这涉及让初始本机方法存根是间接指示JIT编译方法然后修改原始调用以跳过初始存根.当前的紧凑版本在加载时会编译所有类型的方法.

解决泛型的问题.

这是IL规范和JIT在语义方面的最后一次重大更改,而不是其内部实现细节.

添加了几个新的IL指令,并为仪表类型和成员提供了更多的元数据选项.在IL级别也增加了约束.

当JIT编译具有泛型参数的方法(通过包含类显式或隐式)时,它可以为所使用的每种类型设置不同的代码路径(机器代码指令).实际上,JIT对所有引用类型使用共享实现,因为这些引用的变量将表现出相同的语义并占用相同的空间(IntPtr.Size).

每种值类型都将获得为其生成的特定代码,处理堆栈/堆上变量的减小/增加的大小是导致此问题的主要原因.此外,通过在方法调用之前发出约束操作码,非引用类型上的许多调用不需要将值设置为调用方法(此优化也用于非通用情况).这也允许正确处理默认行为,并且当使用非Nullable值类型时,将比较为null的操作删除为无操作(总是为false).

如果在运行时尝试通过反射创建泛型类型的实例,则运行时将验证类型参数以确保它们传递任何约束.这不会直接影响JIT,除非在类型系统中使用它(尽管可能不太可能).



3> Jorge Córdob..:

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

    您的源代码被编译为一个字节代码,称为公共中间语言(CIL).

    来自每个类和每个方法(以及所有其他事物:O)的元数据都包含在生成的可执行文件的PE头中(无论是dll还是exe).

    如果您正在生成可执行文件,则PE Header还包括一个传统的引导程序,它在您执行可执行文件时负责加载CLR(公共语言运行库).

现在,当你执行:

    bootstraper初始化CLR(主要通过加载mscorlib程序集)并指示它执行程序集.

    CLR执行您的主条目.

    现在,类有一个包含方法函数地址的向量表,因此当您调用MyMethod时,将搜索此表,然后对该地址进行相应的调用.启动后,所有表的所有条目都具有JIT编译器的地址.

    当调用其中一个方法时,调用JIT而不是实际方法并控制.然后,JIT将CIL代码编译为适合的体系结构的实际汇编代码.

    编译代码后,JIT进入方法向量表并将地址替换为已编译的代码之一,以便每个后续调用不再调用JIT.

    最后,JIT处理已编译代码的执行.

    如果你调用另一个尚未编译的方法,那么回到4 ...依此类推......


字节码是基于字节值来描述操作的中间语言的通用术语,虽然它通常指的是"代码"的单个字节,但它并不是完全需要的,也不是专门用于java.
正如我之前所说,CIL是字节码,因为我理解它...甚至CLI规范也是如此......我不明白为什么你说它不是

4> Jon Skeet..:

JIT基本上是CLR的一部分.垃圾收集器是另一个.你把互操作责任等放在哪里是另一回事,而且我很不容易发表评论:)



5> Punit Vora..:

我知道线程很老了,但我想我可能会把图片放在让我理解JIT的图片中.这是来自Jeffrey Ritcher的优秀着作CLR到C#.在图中,他所讨论的元数据是在程序集头中发出的元数据,其中存储了有关程序集中类型的所有信息:

CLR通过C#的JIT图像

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有