一。CLS(Common Language Specification)公共语言规范
CLS是在ECMA(European Computer Manufacturers Association-欧洲计算机制造商协会)标准中定义的。CLS包含了有关语言互操作性的规则,即用一种符合CLS的语言写的代码可与另一种符合CLS的语言写的代码进行互操作。这是因为符合CLS的语言写的代码都会被编译为中间语言(IL, Intermediate Lanugage)代码。运行时引擎会执行IL代码。
.NET提供的VB.NET,C#,Visual C++.NET,Visual J#.NET都符合CLS。这些语言写的代码都会被各自的编译器生成一种中间代码,即微软中间语言(MSIL), MSIL使得用.NET语言写的代码可进行互操作。
二。CLI(Common Language Infrastructure)公共语言基础结构
ECMA标准还定义了执行IL代码所需的基础结构所遵循的规范即CLI。CLI提供了通用类型系统(Common Type System)和服务,如类型安全和托管代码执行等。
.NET框架主要包含.NET框架类库(提供了所有.NET语言通用的类型)和公共语言运行库两个主要组件。
.NET框架为每个CLI规范都提供了如下基础结构和服务:
1。公共语言运行库(CLR):CLR由多个组件组成,这些组件为应用程序提供了运行时环境及运行服务,并将应用程序的MSIL代码载入运行库、将MSIL代码编译为本地代码、执行这些代码并强制实现安全性、并提供自动内存管理和线程支持等。如下图:
基类库支持 |
|||
线程支持 |
COM封装器 |
||
异常管理器 |
安全引擎 |
||
类型检查器 |
调试引擎 |
||
代码管理器 |
将IL编译为本机代码的编译器 |
垃圾回收器 |
|
类加载器 |
|||
代码管理器,是在执行期间管理代码。
当执行一个可执行文件时,类加载器会将该文件中的MSIL代码和元数据加载到运行时内存中,在执行代码之前,代码会被传到本机代码编译器(包含于CPU体系结构的JIT(just in time)编译器)中被编译为本机代码和指令集。第一次调用一个方法时,就会经过从MSIL到本机代码的编译,之后在调用时,就会执行已有的JIT编译的代码。
2。通用类型系统(CTS)提供在使用不同语言开发应用程序时所必需的数据类型、值和对象类型。
3。类型安全:.NET框架可确保在一个值或对象上所执行的操作仅对该值或对象发生作用。这就要求每个值或对象都具有类型,且值或对象的引用也有类型。
4。托管代码执行:CLR的不同组件为托管代码提供基础结构和运行时服务的过程,叫做托管代码执行过程。托管执行过程是运行库载入,执行并提供自动内存管理的过程,还有其他的服务,如JIT编译,确保类型安全,强制安全性和处理异常等。
什么是托管代码?什么是元数据?
运行于CLR中的代码叫托管代码,而那些不在CLR中运行的代码叫非托管代码。CLR提供了一个互操作层,允许托管代码和非托管代码之间进行互操作。托管代码是一种自描述代码,可向公共语言运行库提供信息,以获得各种运行时服务。在.NET中,该信息是以元数据的形式与MSIL代码一起存储在可执行文件中。元数据是用于描述代码和该代码所包含的类型的信息。托管代码由垃圾回收过程自动从内存中分配和释放的。托管数据只能由托管代码访问,但托管代码也能访问非托管数据。
5。并行执行:.NET框架允许通过程序集在同一个系统上部署多个版本的应用程序。程序集是.NET框架中开发和部署的基本单元,包含MSIL代码和元数据,元数据包含程序集版本、名称以及该程序集所依赖的其他程序集的版本等信息。CLR使用元数据中的版本信息来确定应用程序的依赖性,使得可以并行运行一个程序的多个版本。
什么是程序集?
程序集是.NET框架中开发和部署的基本单元,包含应用程序所需的类型和资源。多个应用程序共享的程序集就做全局程序集(全局程序集也可以叫共享程序集,具有强名称,强名称包含程序集名、版本、区域信息、数字签名及公钥信息),它存储在全局程序集缓存(GAC)中。GAC是具有整个机器范围的缓存,它包含由多个应用程序共享的程序集。可用程序集为应用程序执行版本控制和安全性配置。
使用强名工具创建密钥的语法:sn –k MyKey.dat
在程序集的AssemblyKeyFile属性中指定包含密钥对的文件名:[assembly:AssemblyKeyFile(“MyKey.dat”)]
在GAC中安装、卸载、查看共享程序集:gacutil /i或者/u <assembly>;通过打开%windir%"Assembly文件夹,在Windows Explorer中查看GAC中所安装的程序集。
三.应用程序域
1.进程(Process):是应用程序运行时所处的执行边界。在进程启动时,所有的运行库环境都会为其分配地址空间。
2。应用程序域:是应用程序运行时所处的边界。一个进程可以包含多个应用程序域。一个应用程序域中应用程序无法直接访问另一应用程序域中的应用程序。若要访问,需要使用代理(代理是一个对象,用于启动进程间通讯),这个隔离使得一个进程中各应用程序域互不影响。就是为安全性,可靠性,隔离性,和版本控制,及卸载程序提供的隔离边界。它通常由运行库宿主创建,应用程序域提供了一个更安全,用途更广的处理单元。
四.装箱和拆箱
装箱和拆箱:是把值类型转换为引用类型的过程,是隐式的,相反的过程就是拆箱,是显式的。
装箱分3部:
1)分配内存空间。包括要装箱的值类型的空间、方法表、SynBlockIndex,其中后两者用来管理引用对象。
2)值复制。把堆栈中要装箱的值复制到堆上。
3)返回引用对象的引用。
拆箱也分3部
1) 检查类型,确保引用类型是装箱的结果。
2)指针返回,返回要拆箱的引用类型中的值的地址。
3)字段拷贝,把引用类型中的字段拷贝到堆栈中。
五。垃圾回收机制?
CLR实现的自动内存管理。需要清楚的几点:
1)什么被认为是可回收的对象?
GC采用一定的算法遍历所有的对象,找出可达对象和不可达对象,不可达对象是可回收的对象。
2)什么时候回收?
通常情况下:内存不足溢出时,确切的说,是第一代对象已满的时候。
3)如何回收?
垃圾收集进程来释放不可达对象的内存空间。
4)回收完后,还需要做什么?
避免托管堆上的内存碎片,重新分配内存,压缩托管堆。
5)避免垃圾回收带来的性能影响,采用代龄机制。