CLR学习之初识CLR
一、什么是CLR?
CLR即公共语言运行时(Common Language Runtime,简称CRL),就是微软为.net产品构建的运行环境,与java的JVM类似,通俗的讲就是.net虚拟机。CLR上实际运行的并不是我们通常所用的编程语言(例如C#、VB等),而是一种字节码形态的“中间语言”。这意味着只要能将代码编译成这种特定的“中间语言”(MSIL),任何语言的产品都能运行在CLR上。CLR通常被运行在Windows系统上,但是也有一些非Windows的版本。这意味着.Net也很容易实现“跨平台”。CLR是.net系列产品运行的基础。
二、CLR与.Net Framework 的关系?
| .NET框架 (.NET Framework) 是由微软开发,一个致力于敏捷软件开发(Agile software development)、快速应用开发(Rapid application development)、平台无关性和网络透明化的软件开发平台。.NET框架是以一种采用系统虚拟机运行的编程平台,以通用语言运行库(Common Language Runtime)为基础,支持多种语言(C#、VB.NET、C++、Python等)的开发。(维基百科.Net Framework) |
.Net Framework是一个支持多种开发语言的开发平台,然而这种多语言支持的特性是以CLR为基础的。
三、CLR是怎样工作的
CLR基本工作原理如下图所示:

如上图所示,从源代码到可执行程序,CLR主要做了以下几件事情:
1.将源代码编译成托管代码
托管模块(Managed Module)是一个标准的Windows可移植执行体(PE),其主要由四个部分组分组成,即PE32或PE32+头、CLR头、元数据、IL(Intermediate Language,中间语言)。
PE32(32位)或PE32+(64位)头
这里描述了当前托管模块的基本信息,包括运行的Windows版本、文件类型、生成时间等。对于包含本地 CPU代码的模块,这个头包含了与本地 CPU 代码有关的信息。
CLR头
包含使这个模块成为一个托管模块的信息(可由 CLR 和一些实用程序 进行解释)。头中包含了需要的 CLR 版本,一些 flag,托管模块入口方 法(Main 方法)的 MethodDef 元数据 token,以及模块的元数据、资 源、强名称、一些 flag 以及其他不太重要的数据项的位置/大小
元数据
每个托管模块都包含元数据表。主要有两种类型的表:一种类型的表 描述源代码中定义的类型和成员,另一种类型的表描述源代码引用的 类型和成员
IL代码
编译器编译源代码时生成的代码。在运行时, CLR 将 IL 编译成本地 CPU 指令
2.将托管模块合并成程序集
CLR实际不和托管模块工作,它和程序集工作。程序集(Assembly)是一个抽象概念,在CLR的世界里,程序集就相当于“组件”。可以从以下两点对程序集有一个初步的认识:
程序集是一个或多个模块/资源文件的逻辑性分组
程序集是重用、安全性以及版本控制的最小单元
为更好的理解程序集与托管模块的关系,请参考此文章:http://wenku.baidu.com/link?url=N-mICQEkfET-BvRMd1SBdffQdcpOm3cvyfFGbIS3zaRVuKYuq4Jf88JB1bROWuXFe-fE05Yow8Bb0YqO1UpNG0piJEALPh_waqe6tCySspe
3.加载运行时程序
生成的每个程序集既可以是可执行的应用程序,也可以是DLL(其中含有一组由可执行程序使用的类型)。当然,最终是由CLR管理这些程序集中代码的执行。Windows 检查好 EXE 文件头,决定是创建32位还是64 位进程之后,会在进程的地址空间中 加载 MSCorEE.dll 的 x86,x64 或 IA64 版本。如果是 Windows 的 x86 版本,MSCorEE.dll 的 x86 版本在 C:\Windows\System32 目录中。如果是 Windows 的 x64 或 IA64 版本,MSCorEE.dll 的 x86 版本在 C:\Windows\SysWow64 目录中,64 位版本(x64 或者 IA64)则在 C:\Windows\System32 目录中(为了向后 兼容)。然后,进程的主线程调用 MSCorEE.dll 中定义的一个方法。这个方法初始化 CLR,加载 EXE 程序集, 然后调用其入口方法(Main)。随即,托管的应用程序将启动并运行。
4.执行程序集中的代码
到目前为止,源代码已经被编译成二进制的IL并且包含在程序集中,而且被CLR加载。但是,直接执行运算的CPU来说二进制的IL还是太高级了,而且不同的CPU支持的指令集也有所差异。因此,CLR在这里还需要对已经编译好的IL再次编译,针对CPU版本生成可以直接运行的CPU指令,这个过程是由JIT(Just In Time)编译器完成的,可以称作“即时编译”。
当第一次执行某个函数时,MSCorEE.dll 的JITCompiler函数会从程序集的元数据中获取该方法和方法的IL,并且分配一块内存地址,然后将IL编译成的本地代码放入这块内存,然后执行内存中的本地代码。
当再次执行这个函数的时候,由于内存中已经存在JIT编译好的本地代码,因此不需要再次进行JIT过程,可以直接执行内存中的本地代码。 可以预知的结果是,这种情况下应用程序启动后第一次调用某个模块所花费的时间要比以后调用这个模块要稍微多一些。
现在,通过本地代码生成技术,已经可以在编译阶段就根据计算机的的实际环境生成本地代码,这样以来就可以在运行时节省JIT编译的时间,提高程序的启动效率。这看起来是一个不错的功能,但是实际上运用的不是很广泛,主要是有一下限制:
编译时生成的本地代码太过于依赖本地环境,一旦环境有变化 (包括操作系统更新、.Net Framework版本更新、CPU更换等),以前生成的本地代码都不再适用。
编译时生成的本地代码必须要和程序集保持同步。
编译时生成的本地代码不能像运行时JIT编译那样根据运行时的情况对代码进行优化。
注:本文主要参考《CLR via C#》,同时参考了博客:CLR基础之一---认识CLR [《CLR via C#》读书笔记]
CLR学习之初识CLR的更多相关文章
- SSH 框架学习之初识Java中的Action、Dao、Service、Model-收藏
SSH 框架学习之初识Java中的Action.Dao.Service.Model-----------------------------学到就要查,自己动手动脑!!! 基础知识目前不够,有感性 ...
- DotNetty网络通信框架学习之初识Netty
p{ text-align:center; } blockquote > p > span{ text-align:center; font-size: 18px; color: #ff0 ...
- 初识CLR
眨眼间我已经实习了半年时间并且转正了,身份也正式从一个学生转变为一个职场人,这个博客自从开始实习以来就一直没有更新过= =没错,就是我懒癌晚期,不过不行!一切都要开始走向正轨,此博会继续见证我的成长, ...
- 01.由浅入深学习.NET CLR 基础系列之CLR 的执行模型
.Net 从代码生成到执行,这中间的一些列过程是一个有别于其他的新技术新概念,那么这是一个什么样的过程呢,有什么样的机制呢,清楚了这些基本的东西我们做.Net的东西方可心中有数.那么,CLR的执行模型 ...
- CLR_Via_C#学习笔记之CLR的执行模型
1:公共语言运行时(Common Language Runtime,CLR)是一个可由多种编程语言使用的“运行时”.CLR的核心功能(比如内存管理.程序集加载.安全性.异常处理和线程同步)可由面向CL ...
- SQL CLR学习
SQL CLR (SQL Common Language Runtime) 是自 SQL Server 2005 才出现的新功能,它将.NET Framework中的CLR服务注入到 SQL Serv ...
- 学习笔记:java并发编程学习之初识Concurrent
一.初识Concurrent 第一次看见concurrent的使用是在同事写的一个抽取系统代码里,当时这部分代码没有完成,有许多的问题,另一个同事接手了这部分代码的功能开发,由于他没有多线程开发的经验 ...
- CLR基础之一---认识CLR [《CLR via C#》读书笔记]
<CLR via C#>读书笔记 什么是CLR CLR的基本概念 通用语言运行平台(Common Language Runtime,简称CLR)是微软为他们的.Net虚拟机所选用的名称.这 ...
- 【CLR】详解CLR中的程序集
目录结构: contents structure [+] 程序集的简介 为程序集分配强名称 如何指定程序集的版本资源信息 如何对程序集签名 全局程序集缓存 如何查看程序集的信息 强命名程序集防串改 1 ...
随机推荐
- Linux系统运行模式介绍
Linux运行模式 自由服务,即不需要用户独立去安装的软件服务,而是在系统安装好之后就可以直接使用的服务(内置服务). 运行模式也称为运行级别,属于linux的自有服务. 运行模式可以理解为一旦你开机 ...
- 十六、python面向对象基础篇
面向对象基础: 在了解面向对象之前,先了解下变成范式: 编程范式是一类典型的编程风格,是一种方法学 编程范式决定了程序员对程序执行的看法 oop中,程序是一系列对象的相互作用 python支持多种编程 ...
- 字符串比较==和equals的区别
<Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?> 比较详细的比较了==和equals方法的区别. 那借此机会,我就来梳理一下 Stack Ov ...
- javascript打开窗口
项目中javascript代码,早期使用了只有ie支持的方法:Window createPopup() 方法 那个时候是2009年,而现在已经是2019-12-11了.如何改造这个早期的代码呢? 找到 ...
- 使用 python set 去重 速度到底是多快呢???
这次去测试一下 python 的set去重,速度怎么样? 我们要做的是把文件一次性读取到内存中,然后去重,输出去重的长度. 第一步:对 121w 条数据去重,看去重话费的时间 上证据: 第二步:对 1 ...
- 201671010456-张琼 实验十四 团队项目评审&课程学习总结
博文简要信息表 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu- ...
- css ie bug 双边距
- JMeter【第四篇】参数化
概念 参数化的原因,并不是网上说的真实模拟不同用户,真实反应服务器性能,而是: 数据唯一性(比如注册名不能一样) 避免数据库查询缓存 如何避免参数化: 去掉唯一性校验的约束 关闭数据库的查询缓存,my ...
- 03-docker入门-创建 docker 镜像
方法1:从运行的容器创建方法2:编写 DockFile 文件创建 方法1: 打包镜像 docker commit -m "Test a change" 610 ubuntu:tes ...
- cmd 计划任务
Schtasks /create /sc ScheduleType /tn TaskName /tr TaskRun [/s Computer [/u [Domain\]User [/p Passwo ...