CLR via C#(一)CLR的执行模型

2023-11-03

一、什么是CLR

CLR全称Common Language Runtime,即公共语言运行时。它可以为所有面向CLR的语言提供运行时的内存管理、程序集加载、安全性、异常处理和线程同步等功能

事实上,CLR并不关心开发者使用的到底是哪种语言,只要这门语言的编译器是面向CLR的,就可以在运行时得到CLR的支持。这是因为这些语言的编译器都会将源代码编译成托管模块

二、什么是托管模块

托管模块是一种标准的Windows可移植执行体文件,需要CLR才能执行。托管模块的组成部分如下图所示:

2.1 IL代码

每个面向CLR的编译器生成的都是IL(中间语言)代码。IL是一种与CPU无关的机器语言,它比大多数CPU机器语言更高级。IL支持访问和操作对象类型,提供了创建和初始化对象的指令,支持调用对象上的虚方法,也支持直接操作数组元素等。所以IL可以看做是一种面向对象的机器语言。在运行时,CLR会将IL编译成本机CPU指令。

2.2 元数据

元数据就是一个数据表的集合。一些数据表描述了模块中定义了什么(类型及其成员),另一些数据表描述了模块引用了什么(导入的类型及其成员)。编译器会同时生成IL代码和描述它的元数据,它们是绑定在一起的,所以永远不会失去同步。

那么元数据有什么用处呢?

  • 可以避免编译时对原生C/C++头和库文件的需求。因为在IL代码中已经包含了有关引用类型/成员的全部信息,编译器可以直接从托管模块中读取元数据。
  • IDE的“智能感知”技术(代码提示、补全)就是通过解析元数据实现的。
  • CLR的代码验证过程使用元数据确保代码只执行类型安全的操作。
  • 元数据允许将对象的字段序列化到内存,将其发送给另一台机器,然后反序列化在远程机器上重建对象的状态。
  • 元数据允许垃圾回收器跟踪对象生命周期(通过元数据知道对象中的哪些字段引用了其他对象)。

三、即时编译(JIT)

前面说了面向CLR的编译器会生成IL代码,这种代码是不能直接执行的,还需要将其转换成本机CPU指令。这就是CLR的JIT(即时)编译器的职责。

来看下面这段代码

public static void Main()
{
	Console.WriteLine("Hello world");
	Console.WriteLine("你好 世界");
}

Main()方法执行之前,CLR会检测出Main()方法中的代码引用的所有类型,并分配一个内部的数据结构来管理对引用类型的访问。比如代码中引用了一个Console类型,CLR会分配一个内部数据结构。在这一结构中,Console类型定义的每个方法都会有一个对应的记录。每条记录都包含一个地址,可以通过地址找到方法的实现。在对这个数据结构进行初始化时,CLR将每个记录项都设置成指向包含在CLR内部的一个未编档函数。假设这个函数叫JITCompiler

Main()方法首次调用WriteLine时,JITCompiler就会被调用。而JITCompiler负责将方法里的IL代码即时编译成本机CPU指令。

那么在JITCompiler中具体干了些什么呢?

  • 首先JITCompiler被调用时,它知道要调用的是哪个方法(WriteLine),以及具体是哪个类型定义了该方法(Console)。
  • 然后JITCompiler会在定义该类型的程序集的元数据中查找被调用的方法的IL。
  • 接下来JITCompiler会验证IL代码,并将其编译成本机CPU指令。这些指令会保存到动态分配的内存块中。
  • 然后JITCompiler回到之前的“内部数据结构”,找到调用方法的那条记录,将其指针指向内存块。
  • 最后JITCompiler跳转到内存块,执行完毕其中的指令,并一路返回Main()

接下来,Main()要执行第二条语句,仍然是WriteLine方法。此时“内部数据结构”中的记录已经指向了编译好指令的内存块,所以会直接执行,完全跳过了JITCompiler。也就是说方法仅在首次调用时会有一些性能损失,以后再次调用时都以本机指令的方式全速运行,无需再次编译。 当然,一旦程序终止,编译好的代码块也会丢弃。所以当再次运行时又需要重新编译。

四、参考资料

[1].《CLR via C# 第四版》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CLR via C#(一)CLR的执行模型 的相关文章

  • c和java语言中的换行符

    现在行分隔符取决于系统 但在 C 程序中我使用 n 作为行分隔符 无论我在 Windows 还是 Linux 中运行它都可以正常工作 为什么 在java中 我们必须使用 n 因为它与系统相关 那么为什么我们在c中使用 n 作为新行 而不管我
  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • VB.NET 相当于 C# 属性简写吗?

    是否有与 C 等效的 VB NET public string FirstName get set 我知道你能做到 Public Property name As String Get Return name ToString End Ge
  • 如何检查QProcess是否正确执行?

    QProcess process sdcompare QString command sdcompare QStringList args sdcompare command sdcompare diff args sdcompare lt
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • 互斥体实现可以互换(独立于线程实现)

    所有互斥体实现最终都会调用相同的基本系统 硬件调用吗 这意味着它们可以互换吗 具体来说 如果我使用 gnu parallel算法 使用openmp 并且我想让他们称之为线程安全的类我可以使用boost mutex用于锁定 或者我必须编写自己
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • Rx 中是否有与 Task.ContinueWith 运算符等效的操作?

    Rx 中是否有与 Task ContinueWith 运算符等效的操作 我正在将 Rx 与 Silverlight 一起使用 我正在使用 FromAsyncPattern 方法进行两个 Web 服务调用 并且我想这样做同步地 var o1
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 如何将整数转换为 void 指针?

    在 C 中使用线程时 我面临警告 警告 从不同大小的整数转换为指针 代码如下 include
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • Linq-to-entities,在一个查询中获取结果+行数

    我已经看到了有关此事的多个问题 但它们已经有 2 年 或更长 的历史了 所以我想知道这方面是否有任何变化 基本思想是填充网格视图并创建自定义分页 所以 我还需要结果和行数 在 SQL 中 这将类似于 SELECT COUNT id Id N

随机推荐

  • 【C语言】让你不再害怕指针——C指针详解(经典,非常详细)

    https blog csdn net qq 41035588 article details 79673674
  • java 读取excel数据

    本文共介绍两种方式 第一种是常规POI读取 第二种是大文件读取 依赖包
  • OpenCV3.3 + Python3.6 开发环境配置

    2018 9 6 更新 Anaconda3 5 2 0版本 Python 3 6 下OpenCV 3 安装 今天重新安装了 Python 的环境 发现在新版本 Anaconda3 下安装配置 OpenCV 3 十分简单 在 Anaconda
  • 【ubuntu虚拟机命令】+ 【mysql数据库】

    ubuntu虚拟机命令 cd 进入家目录 ll 查看文件列表 rm rf 目录名 删除目录 sudo su 从用户切换到 root su ubuntu 从 root 切换到 用户 vi bim 打开文件 i 编辑文件 退出 esc 保存退出
  • 40-400-020-运维-优化-使用MySQLTunner优化MySQL

    文章目录 1 概述 2 安装MySQL 3 下载 4 报告分析 1 概述 MySQLTuner 是一个 Perl 脚本 可以用来分析您的 MySQL 性能 并且基于收集到的信息给出相应的优化建议 这样子 您就可以调整 my cnf 从而优化
  • 关于colmap+nerf对数据集进行预处理的使用总结

    前言 零零碎碎的东西太多 有必要统一记录一下 因为是回忆步骤 所以可能有不准确的地方 Colmap的使用 1 下载 下载链接 colmap 下载之后直接解压就能使用 点击COLMAP bat 2 colmap 这里到处都是很详细的操作步骤
  • Chisel3 - util - LockingArbiter

    https mp weixin qq com s 5oAwH3scumARzPidRBfG2w 带锁多入单出仲裁器 输出会被锁定指定的时钟周期 参考链接 https github com freechipsproject chisel3 b
  • 单片机系统中实用的按键驱动(STM32、51都适用)

    目录 1 自己使用的按键驱动 1 1 驱动源码 1 2 使用方法 2 另一种按键驱动 2 1 驱动源码 2 2 使用方法 在我们嵌入式开发中 产品上往往少不了按键 一个好的按键驱动可以满足不同场合的客户需求 这里我分享几个实用的按键驱动 希
  • Python机器学习笔记 使用sklearn做特征工程和数据挖掘

    特征处理是特征工程的核心部分 特征工程是数据分析中最耗时间和精力的一部分工作 它不像算法和模型那样式确定的步骤 更多的是工程上的经验和权衡 因此没有统一的方法 但是sklearn提供了较为完整的特征处理方法 包括数据预处理 特征选择 降维等
  • 西门子S7-300 PLC 的50个经典问题

    1 使用CPU 315F和ET 200S时应如何避免出现 通讯故障 消息 使用CPU S7 315F ET 200S以及故障安全DI DO模块 那么您将调用OB35 的故障安全程序 而且 您已经接受所有监控时间的默认设置值 并且愿意接收 通
  • Linux 小结

    前言 为了便于理解 本文从常用操作和概念开始讲起 虽然已经尽量做到简化 但是涉及到的内容还是有点多 在面试中 Linux 知识点相对于网络和操作系统等知识点而言不是那么重要 只需要重点掌握一些原理和命令即可 为了方便大家准备面试 在此先将一
  • Python爬虫

    文章目录 1 概述 2 数据采集 3 数据清洗 3 1 读取数据 3 2 去掉车位 地下室 数据 3 3 房源信息解析 4 数据处理及可视化 4 1 各地区二手房源数 4 2 各地区二手房均价 4 3 各地区二手房总价 4 4 各地区二手房
  • subtitle, CC, TTX

    论坛中的一段解答 1 数据广播 我不清楚你所指的数据广播具体是什么 但在DVB T和MHEG的标准里面传送的TTX和SUB这些被称为数据广播 在中国 analog channel里面的TTX信息被称为图文信息 也就是数据广播 也许有错 你可
  • 输入字符串,逆序输出(两种方法)

    问题描述 从键盘上输入一组字符串 实现逆序输出 解题思路 方法一 输出的时候从 n 1 的数据往前依次输出 方法二 假设输入n个字符 字符串默认末尾补上 0 将第0个字符和第 n 1 个字符交换 依次交换中间的数据 输入的数据 H E L
  • 使用js做华为机试题输入输出总结

    1 输入 1 输入一行 进行处理 得到输出 输入用例有多组 while line readline 代码 2 输入两行 进行处理 得到输出 输入用例有多组 while str1 readline str2 readline 代码 2 输出
  • 解决CentOS7系统无法使用中文输入法的问题

    解决CentOS7系统无法使用中文输入法的问题 问题 不能切换中文输入 解决 进入到应用程序 gt Region Language gt 添加 gt 选择 汉语 中国 gt 汉语 Intelligence Pinyin 原文 https b
  • [OpenAirInterface实战-7] :OAI编译环境的架构、搭建、目标代码的编译

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 120556060 目录 第1章 概述
  • Histogram中各个参数详解

    histogram从不会到理解的过程 1 我想先从读取histogram的bins的方法说起 Mat hist 假设已经过calchist 首先 Mat类型的hist 他的维数是dims的 这就决定了 Mat hist中每个bins的存放形
  • Fragment的四种跳转方式

    本文主要记录了关于fragment的四种跳转方式 1 从同一个Activiy的一个Fragment跳转到另外一个Fragment 2 从一个Activity的Fragment跳转到另外一个Activity 3 从一个Activity跳转到另
  • CLR via C#(一)CLR的执行模型

    一 什么是CLR CLR全称Common Language Runtime 即公共语言运行时 它可以为所有面向CLR的语言提供运行时的内存管理 程序集加载 安全性 异常处理和线程同步等功能 事实上 CLR并不关心开发者使用的到底是哪种语言