所知IL是与CPU无关的机器语言,其能访问和操作对象类型,并提供指令来创建和初始化对象,调用对象上的虚方法以及直接操作数组对象等,故可视为一种面向对象的机器语言。每种语言的存在都有其存在的价值和原因,同时各自有各自的优势,由于CLR的独特性,可以尝试用不同语言描述不同功能(必须是面向CLR的编译器语言)。
在方法执行时,需把方法的IL转换成本机CPU指令,这是JIT编译器的职责。一个方法首次调用时:
CLR在Main方法执行之前会检测其代码所引用的所有类型,并分配一个内部数据结构来管理对引用类型的访问。例如在Main方法内有Console.WriteLine("");
此时在这个内部数据结构,Console类型定义的每个方法都有一个对应的记录项,每个记录项都含有一个地址,根据此地址找到方法的具体实现。对这个结构初始化时,CLR将每个记
录项都设置成包含在CLR内部的一个未编档函数。该函数称为JITCompiler。当首次调用WriteLine时,JITCompiler函数会被调用,并将方法的IL代码编译成本机的CPU指令,保存到
动态分配的内存块中。然后JC回到CLR为类型创建内部数据结构,找到被调用方法对应的那条记录,修改最初对JC的引用使其指向内存块的地址,最后JC函数跳转到内存块中的代码
(方法的具体实现),代码执行完毕返回继续执行后续代码。
整个过程有点繁琐,大致就是分两步走,第一步找到具体方法的地址,初始化数据结构,编译成指令。第二步回到CLR找到方法的记录,执行完毕返回。当Main再次调用WriteLine时,由于对WriteLine的代码进行了验证和编译,所以会直接执行内存块中的代码,完全跳过JC函数。很显然,当应用程序终止,编译好的代码也会被丢弃。(粗浅了解,忘指证)
时间: 2024-11-23 21:15:55