第一章 CLR执行模型
热点重点
- 公共语言运行库(CLR,Common Language Runtime):
- 一个运行库
- 编译器:
- 面向CLR的编译器,能编译出托管模块。C++编译器可编译出非托管模块代码
- 托管模块(managed module):
- 是编译器编译的结果
- 结构:中间语言和元数据
- 具体结构:PE32或PE32+头,CLR头,元数据,IL代码
- 中间语言(IL,Intermediate Language):
- 在运行时,CLR将其编译成本地CPU指令
- 可理解为面向对象的机器语言
- 元数据(metadata):
- 一系列特殊的数据表,描述模块定义的内容
- 程序集(assembly):
- 一个或多个模块/资源文件的逻辑性分组。在CLR中也称为“组件(component)”
- JIT(just-in-time)编译器:
- 将IL转换成本地CPU指令
- 不安全代码:
- C#编译器对不安全代码打上unsafe关键字来标记
- System.Security.Permissions.SecurityPermissionsFlag = ~.SkpiVerification 时,允许执行不安全代码
- 可利用PEVerify.exe查看程序集中是否含有不安全代码
- WoW64(windows on windows64)技术:
- 允许运行32位Windows应用程序
- Win64,Itanium用该技术运行32位程序
- Itanium机器:
- CPU为IA64版本,与x64和x86版本不同
- 拥有WoW64技术,可运行32位程序
- 编译器优化代码
- 托管程序比非托管程序的性能要高
执行模型
- 加载程序集到内存
- 执行某个方法时候先查看是否已编译为本地代码。
第一次调用:调用JIT编译IL为本地代码保存在内存中。
对程序性能造成极小的影响,并会分配动态内存。
以后的调用:直接找到内存中已经编译过的代码,而直接跳过JIT编译。
- 由于托管代码生成的CPU指令具有特别强的针对性,而且微软把JIT编译的消耗降到了最低最低,
所以托管代码比非托管代码性能更高
| 代码形式 | 运行形式 | 性能(相对) |
|
非托管代码 | 静态的CPU指令 | 直接读取 | 低 |
|
托管代码 | 中间语言IL | 由CLR读取,并由JIT生成 针对性CPU指令 | 高 |
|
JIT编译IL为本地代码
本地代码生成器:NGen.exe。由.NET Framework配套提供。
功能:可以将IL代码编译为本地代码。
作用:
- 提高程序启动速度(JIT无需再编译IL代码)
- 减少应用程序的工作集,可以将程序集编译为IL代码,于是运行时候JIT无需再编译
缺点:
- 可能失去同步。如果发布了新版本的程序集,那么JIT也不会编译IL代码而是直接用NGen.exe所生成的本地代码。
- 没有知识产权保护。生成的本地代码脱离了原IL代码,但是运行时,CLR要求访问程序集的元数据,所以要同时发布包含IL和元数据的程序集。
- 执行性能差。因为不是JIT编译,所以如果移植后,不能对CPU进行针对性代码生成。
- 加载性能差。牵涉到内存分配,如果JIT编译的话可以动态分配,NGen.exe生成的程序集以静态方式计算内存地址引用,若windows不能再其首选基址加载程序集,则会重新定位文件
?查看电脑的.NET Framework版本
先查看是否安装了.NETFramework ,资源浏览器输入:%SystemRoot%\System32,查看存在文件 mscoree.dll,则已安装。
- 注册表方式
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\policy
- VS命令行方式
在”VS工具命令提示“的窗口中输入:CLRVer.exe -all
- CMD命令行方式
dir %WINDIR%\Microsoft.Net\Framework\v*
- 资源浏览器方式
输入:%systemroot%\Microsoft.NET\Framework