.NET 公共语言运行时 (CLR)

17 Mar 2025 | 6 分钟阅读

.NET CLR 是一个运行时环境,用于管理和执行用任何 .NET 编程语言编写的代码。CLR 是 .NET 框架的虚拟机组件。该语言的编译器将使用 .NET 兼容语言开发的应用程序的源代码编译成 CLR 的中间语言,称为 MSIL,即 Microsoft 中间语言代码。此代码是平台无关的。它类似于 Java 中的字节码。在编译期间也会生成元数据,MSIL 代码与元数据一起存储在一个称为清单文件的文件中。此元数据通常是 CLR 执行 MSIL 代码所需的成员和类型。CLR 的即时编译器组件将 MSIL 代码转换为机器的本地代码。此代码是平台相关的。CLR 管理内存、线程、异常、代码执行、代码安全、验证和编译。

下图显示了源代码转换为本地代码的过程。

Net Common Language Runtime

上图 将代码转换为 CPU 可以执行的本地代码。

CLR 的主要组件是

  • 通用类型系统
  • 通用语言规范
  • 垃圾回收器
  • 即时编译器
  • 元数据和程序集
Net Common Language Runtime

1. 通用类型系统

CTS 提供运行时声明、使用和管理数据类型的指南。它提供跨语言通信。例如,VB.NET 有一个整数数据类型,C# 有一个 int 数据类型来管理整数。编译后,这两个数据类型都使用 Int32。因此,CTS 使用托管代码提供数据类型。通用类型系统有助于编写与语言无关的代码。

它提供两种类型的类别。

  1. 值类型: 值类型将数据存储在分配在堆栈上的内存中或结构中内联。此类型类别直接保存数据。如果一个变量的值被复制到另一个变量,则两个变量独立存储数据。它可以是内置类型、用户定义类型或枚举类型。内置类型是基本数据类型,如数字、布尔值、字符和日期。用户在源代码中创建用户定义类型。枚举是指一组枚举值,由标签表示但存储为数字类型。
    Net Common Language Runtime
  2. 引用类型: 引用类型存储内存地址值的引用,并分配在堆上。堆内存用于动态内存分配。引用类型不直接保存实际数据,而是保存数据的地址。每当创建引用类型对象时,它复制地址而不是实际数据。因此,两个变量将引用相同的数据。如果一个引用类型对象的数据发生更改,则其他对象也会反映相同的更改。引用类型可以是自描述类型、指针类型或接口类型。自描述类型可以是字符串、数组和类类型,它们存储关于自身的元数据。

2. 公共语言规范 (CLS)

公共语言规范 (CLS) 包含所有 .NET 支持的语言都必须遵循的一组规则。这些通用规则使得实现语言集成变得容易,并有助于跨语言继承和调试。NET 框架支持的每种语言都有自己的语法规则。但 CLS 确保了使用 .NET 语言开发的应用程序之间的互操作性。

3. 垃圾回收

垃圾回收器是 CLR 的一个组件,它作为自动内存管理器工作。它通过根据需求自动分配内存来帮助管理内存。它为对象分配堆内存。当对象不再使用时,它会回收分配给它们的内存以供将来使用。它还通过不允许一个对象使用另一个对象的内容来确保对象的安全性。

4. 即时 (JIT) 编译器

JIT 编译器是 CLR 的重要组成部分。它将 MSIL 代码转换为本地代码(即机器特定代码)。.NET 程序可以显式或隐式编译。开发人员或程序员在显式编译中调用特定的编译器来编译程序。在隐式编译中,程序编译两次。在第一次编译过程中,源代码被编译成 Microsoft 中间语言 (MSIL)。在第二次编译过程中,MSIL 代码被转换为本地代码。这个过程称为 JIT 编译。JIT 编译器有三种类型——Pre、Econo 和 Normal。Pre JIT 编译器在执行前将整个 MSIL 代码编译成本地代码。Econo JIT 编译器只编译执行期间需要的 MSIL 代码部分,并删除不再需要的部分。Normal JIT 编译器也只编译执行期间需要的 MSIL 代码部分,但将它们放入缓存以供将来使用。它不需要重新编译已使用过的部分,因为它们已被放入缓存内存中。

5. 元数据

元数据是关于程序的二进制信息,可以与 MSIL 代码一起存储在 CLR 可移植可执行文件 (PE) 中,也可以存储在内存中。在 MSIL 执行期间,元数据也会加载到内存中,以便正确解释类和相关信息。因此,元数据有助于以语言中立的方式实现代码或实现语言互操作性。

6. 程序集

程序集是物理代码分组的基本单元。它由程序集清单、元数据、MSIL 代码和一组资源(如图像文件)组成。它也被认为是基本的部署单元、版本控制、重用、安全权限等。

.NET CLR 功能

以下是 CLR 的功能。

  • 它将程序转换为本地代码。
  • 处理异常
  • 提供类型安全
  • 内存管理
  • 提供安全
  • 提高性能
  • 语言独立
  • 平台独立
  • 垃圾回收
  • 为面向对象程序提供继承、接口和重载等语言特性。

在 CLR 中运行的代码称为托管代码,而 CLR 之外的代码称为非托管代码。CLR 还提供了一个互操作层,允许托管代码和非托管代码进行互操作。

1. 托管代码

任何用 .NET 框架编写的语言都是托管代码。托管代码使用 CLR,它通过管理内存、处理安全性、允许跨语言调试等来照看您的应用程序。托管代码的过程如下图所示

Net Common Language Runtime

2. 非托管代码

在 .NET 框架之外开发的代码称为非托管代码。不受 CLR 控制运行的应用程序被称为非托管应用程序。某些语言(如 C++)可用于编写此类应用程序,例如操作系统的低级访问函数。与 VB、ASP 和 COM 的后台兼容性是非托管代码的示例。此代码在包装类的帮助下执行。非托管代码过程如下所示

Net Common Language Runtime

.NET CLR 版本

CLR 会不时更新自己以提供更好的性能。

.NET 版本CLR 版本
1.01.0
1.11.1
2.02.0
3.02.0
3.52.0
44
4.54
4.64
4.64

.NET CLR 结构

以下是公共语言运行时的组件结构。

Net Common Language Runtime

基类库支持

它是一个类库,支持 .NET 应用程序的类。

线程支持

它管理多线程应用程序的并行执行。

COM 封送器

它提供 COM 对象和应用程序之间的通信。

安全引擎

它强制执行安全限制。

调试引擎

它允许您调试不同类型的应用程序。

类型检查器

它检查应用程序中使用的类型,并验证它们是否符合 CLR 提供的标准。

代码管理器

它在执行运行时管理代码。

垃圾回收器

它释放未使用的内存并将其分配给新应用程序。

异常处理器

它在运行时处理异常,以避免应用程序失败。

类加载器

它用于在运行时加载所有类。


下一个主题.NET 框架类库