CLR叫做公共语言运行时(Common Language Runtime),它是所有.NET应用程序运行时环境,是所有.NET应用程序都使用的编程基础,它如同一个支持
.NET Framework,运行一个
.NET程序也必须安装。公共语言运行时遵循公共语言架构的标准,能够使C++、C# 、Visual Basic、以及JScript等多种语言深度集成。
定义
公共语言运行时(Common Language Runtime,CLR)是Microsoft的公共语言中基础结构(
CLI)的一个商业实现,CLI是一种国际标准,用于创建语言和库在其中无缝协同工作的执行和开发环境基础。.NET Framework 提供了一个称为公共语言运行时的运行环境,它运行代码并提供使开发过程更轻松的服务。有了公共语言运行时,就可以很容易的设计出对象能够跨语言交互的组件和应用程序。也就是说,用不同语言编写的对象可以互相通信,并且它们的行为可以紧密集成。
公共语言运行时遵循公共语言架构的标准,能够使
C++、
C#、
Visual Basic、以及
JScript等多种语言深度集成。CLR从某种意义上理解相当于Java中的
Java虚拟机(JVM),而MSIL相当于Java中的
字节码(.class文件)。MSIL总是及时编译(称为JIT编译)为相应平台的机器代码,这一点与Java也很相似。
托管执行过程
公共语言运行时的功能通过编译器和工具开发,开发者可以编写利用此托管执行环境的代码。使用基于公共语言运行时的语言编译器开发的代码称为
托管代码,反之则被称为
非托管代码。托管代码有很多优点,例如跨语言集成、跨语言异常处理、增强的安全性、版本控制和部署支持、简化的组件交互模型、调试和分析服务等。
执行托管代码的过程包括以下4个步骤:
选择编译器
为获得公共语言运行时提供的优点,必须使用一个或多个针对运行时的语言编译器。例如 Visual Basic、C# 、Visual C++、F#或其它的第三方编译器(如
Eiffel、
Perl或
COBOL编译器)中的一个。
将代码编译为Micrisoft中间语言
编译将源代码翻译为Micrisoft 中间语言(MSIL)并生成所需的
元数据。MSIL是一组可以有效地转换为本机代码且独立于CPU的指令。它包括用于加载、存储和初始化对象以及对对象调用方法的指令,还包括用于算术和逻辑运算、控制流、直接内存存取、异常处理和其他操作的指令。元数据描述代码中的类型,包括每种类型的定义、每种类型的成员的签名、代码引用的成员和运行时在执行时使用的其他数据。
将SMIL翻译为本机语言
在执行时,实时(JIT)编译器将MSIL翻译为本机代码。在此编译过程中,代码必须通过验证过程,该过程检查MSIL和元数据以查看是否可以将代码确定为类型安全。
运行代码
公共语言运行时提供使托管代码能够发生及可在执行期间使用的各种服务的基础结构。
自动内存管理
自动内存管理是公共语言运行时在托管执行过程中所能提供的服务之一。公共语言运行时的垃圾回收器为应用程序管理内存的分配和释放。对开发者而言,这意味着开发托管应用程序时不必编写执行内存管理任务的代码。自动内存管理可解决常见问题,例如忘记释放对象并导致内存泄露,或尝试访问已释放对象的内存。
分配内存
初始化进程时,CLR为进程保留一个连续的地址空间区域。这个保留的地址空间被称为托管堆。托管堆上部署了所有引用类型,应用程序创建第一个引用类型时,将为托管堆的基址中的类型分配内存。从内存堆中分配内存要比非托管内存分配速度快。由于CLR通过为
指针添加值来为对象分配内存,所以这几乎和
堆栈中分配内存一样快。另外,由于连续分配的新对象在托管堆中是连续存储,所以应用程序可以快速访问这些对象。
释放内存
垃圾回收器的优化引擎根据所执行的分配决定执行回收的最佳时间。垃圾回收器在执行回收时会释放应用程序不再使用的对象的内存。它通过检查应用程序的根本来确定不再使用的对象。每个应用程序都有一组根,每个根或者引用托管堆中的对象,或者设置为空。
级别和性能
运行时的垃圾回收算法基于以下几个普遍原理。首先,压缩托管堆的一部分内存要比压缩整个托管堆速度快。其次,较新的对象生存期较短,而较旧的对象生存期则较长。最后,较新的对象趋于相互管理,并且大致同时由应用程序访问。
为优化垃圾回收机制的性能,将托管堆分为3代:第0代、第1代和第2代。运行时的垃圾回收器将新对象存储在第0级中。在应用程序生存期的早期创建的对象如果未被回收,则被升级并存储在第1级和第2级中。
为非托管资源释放内存
对于应用程序创建的大多数对象,可以依赖垃圾回收器自动执行必要的内存管理任务。但是,
非托管资源需要显式清除。最常用的非托管资源类型是包装操作系统资源的对象,例如,
文件句柄、
窗口句柄或网络连接。
垃圾回收器可以跟踪封装非托管资源的托管对象的生存期,但是无法具体了解如何清理资源。创建封装非托管资源的对象时,可以在公共Dispose()方法中提供必要的代码以清理非托管资源。通过提供Dispose()方法,对象的用户在使用完对象后显式释放其内存。
CLR的组件
CLR叫做公共语言运行时(Common Language Runtime)。它是所有.NET应用程序运行时环境,是所有.NET应用程序都使用的编程基础,它如同一个支持.NET Framework,运行一个.NET程序也必须安装。CLR也可以看作一个在执行时管理代码的代理,管理代码是CLR的基本原则,能够被管理的代码成为
托管代码,反之称为
非托管代码。CLR包含两个组成部分,CLS(
公共语言规范)和CTS(
通用类型系统)。下面我们通过理解.NET的编程技术来具体了解这两个组件的功能。
公共类型系统
公共类型系统(Common Type System,CTS)。CLR通过公共类型系统和公共语言规范定义了标准数据类型和语言间互操作性的规则。
C#和
VB.NET都是公共语言运行时的
托管代码,它们的语法和
数据类型各不相同。CLR是如何对这两种不同的语言进行托管的呢?
通用类型系统(Common Type System)用于解决不同语言的
数据类型不同的问题,如C#中的
整型是int,而VB.NET中是Integer,通过CTS我们把它们两个编译成通用的类型Int32。所有的.NET语言共享这一类型系统,在它们之间实现无缝互操作。
公共类型系统支持.NET Framwork提供的常用两种类型:值类型和引用类型。其中每一类又可以细分成子类型。公共类型系统所执行的功能如下:
(1)建立一个支持跨语言的集成、类型安全和高性能代码执行的框架;
(2)提供一个支持完整实现多种编程语言的面向对象的模型;
(3)定义各语言必须遵守的规则,有助于确保用不同语言编写的对象能够交互作用。
公共语言规范
公共语言规范(Common Language Specification,CLS)。公共语言规范是一组结构和限制条件,它是公共类型系统的子集,它们一起定义了允许不同编程语言的标准集,由这些编程语言编写的应用程序可以互操作。
编程语言的区别不仅仅在于类型,语法或者说语言规范也都有很大的区别。因此.NET通过定义
公共语言规范(Common Language Specification),限制了由这些不同点引发的
互操作性问题。CLS是一种最低的语言的标准,制定了一种以.NET平台为目标的语言所必须支持的最小特征,以及该语言与其他.NET语言之间实现
互操作性所需要的完备特征。凡是遵守这个标准的语言在.NET
框架下都可以实现互相调用。例如,在C#中命名是区分大小写的,而VB.NET不区分大小写,这样CLS就规定,编译后的
中间代码必须除了大小写之外有其他的不同之处。
为了实现跨语言开发和跨平台的战略目标,.NET所有编写的应用都不是编译为
本地代码,而是编译成微软
中间代码MSIL(Microsoft Intermediate Language)。它将由JIT(Just In Time)编译器转换成机器代码。C#和VB.NET代码通过它们各自的编译器编译成MSIL,MSIL遵守通用的语法,
CPU不需要了解它,再通过
JIT编译器编译成相应的平台专用代码,这里所说的平台是指我们的操作系统。这种
编译方式实现了代码托管,还能够提高程序的运行效率。
优点
使用公共语言运行时有许多优点,部分优点如下:
(1)它使程序的性能得到了改进;
(2)能够轻松的使用其他语言开发的组件;
(3)支持语言功能,例如面向对象编程的继承、接口和重载;
(4)允许创建多线程的可放缩应用程序的显示自由线程处理支持;
(6)自定义特性支持;
(7)垃圾回收机制;
(8)使用委托取代
函数指针,从而增强了类型安全和安全性。