欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 »  .NET本质论第一卷:公共语言运行库教程 » 正文

本教程章节列表

.net本质论-第六章:方法

创建时间:2012年12月06日 19:00  阅读次数:(4811)
分享到:
前面几章建立了一个这样的世界:类型、对象和值可以被动态地实现,并且能被引用、创建,甚至在某种情形下被销毁。然而,最令人感兴趣的地方还是通过调用方法来处理类型、对象或值,因为这是这三个实体相互作用的主要方式。

方法和JIT编译


CLR只执行本机的机器代码。如果一个方法体由CLL组成,那么它就必须在调用之前被转换为本机的机器码。在第1章曾经简要地讨论过,将CIL转换到本机的机器码有两种解决的方法。默认的场景是推迟转换,直到该组件被加载到内存中时。这种解决之道被称为实时编译[just-in-time(JIT),compilation],或简称为JIT编译(JIT-compiling).另一种场景是当组件被首次安装到部署机器上时,生成一个本机映像( native image)。这种解决之道被称为预编译( precompiling)。CLR提供了一个部署丁具(NGEN.EXE)和一个底层库(MSCORPE.DLL),用于在部署时产生本机映像。

当NGEN.EXE和MSCORPE.DLL产生本机映像时,这个本机映像便以一种机器码缓存的形式存储在磁盘上,以便加载器可以发现它。当加载器试图加载一个基于CIL版本的程序集时,它就会在缓存中查找对应的本机映像,并尽可能地使用本机的机器码。如果没有发现合适的本机映像,CLR将使用程序集初始加载时基于CIL的版本。

尽管在部署时产生本机代码听起来很有吸引力.但它并不是没有缺点。代码尺寸就是不将本机映像缓存到磁盘上的理由之一 。按照常规,IA-32机器码比对应的CIL要大得多。对于一个常规组件.常用的可能只是很少的几个方法。当CIL产生一个本机映像时,新的DLL将会包含每个方法的本机代码,包含那些可能从来不会被调用的方法,或者偶尔被调用的方法,例如,初始化、终结代码或者错误处理代码。由于包含了每个方法的实现,因而导致内存代码总的尺寸不必要地增长。更糟糕的是个别方法体的位置没有顾及到运行程序的动态性。由于在代码生成后你不能改变由NCEN.EXE所生成本机映像中方法的位置,因此,对于本来就不多的必需方法,各个方法还可能占用不同的虚拟内存页。这个碎片对于应用程序的工作集尺寸将产生负面的影响。

关于缓存本机映像的第二个问题是:处理跨组件的约定(cross-component contract).对于CLR生成的本机代码,方法使用的所有类型对于译码器(translator) 必须是可见的,因为本机代码必须包按传统的C、c++、COM和WIN32约定下的非虚拟偏移。当方法依赖于另一个组件的类型对.这种跨组件侬赖性就会产生问题,原因就是对于另一个组件的任何改变将会使得缓存的本机代码无效。由此,每个模块在它被编译时都被赋予了一个模块版本标识符(module version identifier,MVID)。MVID是一个简单的唯一标识符,它保证对于一个模块的特定编译是唯一的。

当CIR生成并缓存一个本机映像时,用于生成本机映像(包括那些来自外部的程序集)的每个模块的MVID就存储在本机代码中。当CLR加载器试图加载一个缓存的本机映像时,在CIL到本机代码生成过程中,它首先检查组件的MVID.以核实它们没有被重新编译。如果发生了重新编译,CLR将忽略缓存的本机代码,并退回到包含CIL的组件版本。

如果在缓存中没有发现本机映像(或者由于依赖项重新编译而失效),CLR就会加载该组件的基于CIL的版本。在这种情形下,CLR在方法被首次执行前实时编译(JIT)它们。当方法被实时编译时,CLR必须加载该方法用作参数或局部变量的任何类型。这时,CLR就可能需要(也可能不需要)实时编译任何将被该方法调用的下级( subordinate)方法。为了理解实时编译是如何工作的,让我们看一小段比较乏味的代码。回想一下第4章关于强制类型转换的讨论,CIR为每个类型在其初始化时分配了一个内存数据结构。在CLRl.0的版本下,该数据结构在内部被称为CORINFO_是CLASS.STRUCT,并且通过存储在每个对象中的RuntimeTypeHandle引用。对于lA-32处理程序,在方法表之前的CORINFO_CLAsS—STRUCT有40个字节的头信息。方法表是一个带有长度前缀的内存地址数组,每个方法都有一个入口项。与c+或COM不同的是.CLR方法表既包含实例方法的入口项,又包括静态方法的入口项。
来源:.net学习网
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf】

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 30+68=? 的结果(结果是:98)
结  果: