CLR(Common Language Runtime,公共语言运行时)是.NET Framework框架中最核心的内容,所谓CLR的执行模型,简单地讲就是解释在.NET平台下代码是如何编译和运行的。用一幅图概括如下:
下面是各个阶段的工作。
1,将源代码编译成托管模块
Microsoft已创建了针对各个语言的编译器,编译时编译器会去分析源代码和检查代码的语法,如果没有问题则能顺利通过编译,最终生成一个托管模块(managed module),托管模块由四部分组成,如下图所示。
1> PE32文件头:如果使用PE32格式,表明文件在windows的32位和64位版本都能运行,如果使用PE32+格式,表明文件只能在windows的64位版本上运行。PE32文件头标识了文件类型和文件的生成时间。
2> CLR头:包含了需要的CLR版本,一些标志(flag),托管模块入口方法(Main方法)的MethodDef元数据标记(token)等。
3> IL代码:即中间语言代码,是编译器编译源代码时生成的代码。在运行时,CLR(JIT编译器)将IL代码编译成本地代码(或称本地CPU指令)。
4> 元数据:其实就是一个表的集合,一种类型的表描述源代码中定义的类和成员,另一种类型的表描述源代码所引用的类和成员。
2,将托管模块合并成程序集
CLR实际不和托管模块一起工作,而是和程序集一起工作的。程序集是一个或多个托管模块,以及资源文件(比如图片和html静态页面)的逻辑组合。下图解释了托管模块是如何合并成程序集的。
注:程序集中有一个清单文件manifest,它是由元数据表构成的表集合,这些表描述了构成程序集的所有文件,以及与程序集关联的资源或数据文件。
3,执行程序集的代码
要想执行程序集的代码,CLR的JIT编译器首先会把IL代码编译成本地代码。下图解释了JIT编译器是如何把IL代码编译成本地代码然后执行的。
注:一个方法只有在首次调用时才会进行IL代码验证和编译为本地代码,当第二次调用时不需要再进行IL代码验证和编译,直接执行内存块中的本地代码。但是一旦应用程序终止再次运行应用程序,或者同时启动应用程序的两个实例(使用两个不同的操作系统进程),JIT编译器必须再次进行IL代码验证和编译,因为此时存储在内存中的本地代码已经丢失。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库