《NET CLR via C#》---第三章("运行时"解析类型引用)
1.《NET CLR via C#》笔记---第一章(CLR,托管模块,程序集,JIT,AOT,IL,FCL,CTS,CLS)
2.《NET CLR via C#》---第三章("运行时"解析类型引用)
3.《NET CLR via C#》---第四章(System.Object,类型转换,is和as,命名空间和程序集,运行时的相互关系)4.《NET CLR via C#》---第五章(基元类型,引用类型和值类型,对象相等性和同一性,对象哈希码)5.《NET CLR via C#》---第六章(类型成员,类型的可访问性,友元程序集,分部类型,CLR调用方法指令)6.《NET CLR via C#》---第七章(常量,读/写字段,可读字段)7.《NET CLR via C#》---第八章(类的实例构造器,结构的实例构造器,类型构造器,操作符重载方法,转换操作符,扩展方法)8.《NET CLR via C#》---第十章(无参属性,对象和集合初始化器,匿名类型,元组,有参属性)9.《NET CLR via C#》---第十一章(事件)10.《NET CLR via C#》---第十二章(泛型)"运行时"解析类型引用
- 首先在"C:\Users\LH89\source\repos"目录下,新建Console1工程(C#控制台)
- 实现简单的代码,并编译为程序集(假定名为Program.exe)
using System;
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
}
}
- 运行应用程序,CLR会加载并初始化自身,读取程序集的CLR头,查找标识了应用程序入口方法(Main)的MethodDefToken,检索MethodDef元数据表找到方法的IL代码在文件中的偏移量,将IL代码JIT编译成本机代码,最后执行本地代码。
- 通过对程序集运行ILDasm.exe并选择“视图/显示字节”,双击树形视图中的Main方法。
- 对这些代码进行JIT编译,CLR会检测所有类型和成员引用,加载它们的定义程序集(如果尚未加载)。
- 上述代码包含对System.Console.WriteLine的引用。具体来说,IL call指令引用了元数据token 0A000011。该token标识MemberRef元数据表(表0A)中的记录项。CLR检查该MemberRef记录项,发现它的字段引用了TypeRef表中的记录项(System.Console类型)。按照TypeRef记录项,CLR被引导至一个AssemblyRef记录项:“mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089”,这时CLR就知道了它需要的是哪个程序集。接着,CLR必须定位并加载该程序集。
- 解析引用的类型时,CLR可能在以下三个地方找到类型。
- 相同文件
编译时便能发现对相同文件中的类型的访问,这称为早期绑定。类型直接从文件中加载,执行继续。 - 不同文件,相同程序集
“运行时”确保被引用的文件在当前程序集元数据的FileDef表中,检查加载程序集清单文件的目录,加载被引用的文件,检查哈希值以确保文件完整性。发现类型的成员,执行继续 - 不同文件,不同程序集
如果引用的类型在其他程序集的文件中,“运行时”会加载被引用程序集的清单文件。如果需要的类型不在该文件中,就继续加载包含了类型的文件。发现类型的成员,执行继续。
- 在上例中,CLR发现System.Console在和调用者不同的程序集中实现。所以,CLR必须查找哪个程序集,加载包含程序集清单的PE文件。然后扫描清单,判断是哪个PE文件实现了类型。如果被引用的类型就在清单文件中,一切都很简单。如果类型在程序集的另一个文件中,CLR必须加载那个文件,并扫描其元数据来定位类型。然后CLR创建它的内部数据结构来表示类型,JIT编译器完成Main方法的编译。
本文作者:陈侠云
本文链接:https://www.cnblogs.com/chenxiayun/p/18330374
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步