带着问题读CLR via C#(笔记一)CLR的执行模型

Q1: 什么是CLR?

A1: CLR (Common Language Runtime) 是一个可以由多种编程语言使用的“运行时”。

Q2: CLR的核心功能有哪些?

A2: 1)内存管理;2)程序集加载;3)安全性;4)异常处理;5)线程同步

Q3: CLR与使用的编程语言有关吗?

A3: 无关。只要编译器是面向CLR的就行。

Q4: 选用不同编程语言经过面向CLR的编译器编译后生成的结果相同吗?

A4: 相同。无论选择什么语言,相应的编译器变异的结果都是一个托管模块,即一个标准的32位PE (Portable Executable) 32文件或64位PE32+文件。它们都需要CLR才能执行。

Q5: 托管模块的组成部分是什么,它们的作用分别是什么?

A5: 1)PE32或PE32+头;2)CLR头;3)元数据;4)中间语言

PE32头:1)标识了文件类型(GUI, CUI, DLL);2)包含一个文件生成时间的时间标记;3)包含与本地CPU代码有关的信息(在该模块包含CPU代码的情况下)。

CLR头:1)包含需要的CLR版本;2)托管模块入口方法的MethodDef元数据标记;3)模块的元数据,资源,强名称,一些标记以及不太重要的数据项的位置及大小。

元数据:1)包含描述源代码中定义的类型及成员的元数据表;2)包含描述源代码中引用的类型和成员。

中间语言:编译器编译源代码生成的代码,运行时会被CLR编译为本地CPU指令。

Q6: 什么是程序集?

A6: 程序集是一个抽象的概念,它是一个或多个模块/资源文件的逻辑分组,也是重用,安全性以及版本控制的最小单元。 生成的程序集既可以是一个可执行文件(exe)也可以是一个DLL.

Q7: 托管模块和程序集之间的关系是什么?

A7: 默认情况下,编译器实际会把生成的托管模块转换为程序集,程序集的清单中会指明该程序集仅有一个文件构成。如果项目中只有一个托管模块,没有资源文件或数据文件,那么程序集就是托管模块。如果想将多个文件合并到一个程序集,则需要使用其他工具来实现。

Q8: 方法执行的过程是什么?首次执行和之后执行有区别吗?

A8: 执行一个方法需要将程序集中的IL转换为本地CPU指令,这项工作由CLR的JIT(即时)编译器来完成。用如下例子讲解:

代码如下:

static void Main()
{
    Console.WriteLine("Hello");
    Console.WriteLine("GoodBye");
}

分析准备阶段:

1)      CLR检测Main代码引用的所有类型,此例中为Console类型;

2)      CLR分配一个内部数据结构,用于管理对引用的类型(即Console类型)的访问。Console类型中的所有方法在这个内部结构中都有一个入口, 通过该入口可以找到方法的具体实现;对该内部结构初始化时,CLR将每个方法的入口都设置成指向JITCompiler函数(CLR内部未文档化的一个函数);

执行阶段:

1)      Main方法中首次调用WriteLine方法时,JITCompiler函数会被调用,这个函数知道调用的是哪个方法(WriteLine),以及什么类型(Console)调用了该方法;

2)      JITCompiler在定义了该类型的程序集元数据中查找该方法(WriteLine)的IL,并对IL进行验证,若无误,则将该IL编译为本地CPU指令;

3)      将本地CPU指令保存至一个动态分配的内存块;

4)      JITCompiler返回最初为Console类型创建的内部结构,找到WriteLine方法的入口,并将之前设置的指向JITCompiler的引用改为指向保存本地CPU指令的内存块;

5)      JITCompiler回到保存本地CPU指令的内存块,并执行该指令。

当Console.WriteLine("Hello")执行结束后,继续执行下一行代码Console.WriteLine("Goodbye"),由于Console.WriteLine方法已经编译为本地CPU指令了,就会跳过JITCompiler函数的繁琐操作,直接执行本地CPU代码。但当应用程序终止后再次启动运行这段代码,JIT编译器必须重新将IL编译为本地CPU指令,因为之前是保存在内存块中的,程序终止后内存块会被清空。

Q9: IL有什么优势?

A9: IL可以提高应用程序的健壮性和安全性。在将IL编译为本地CPU指令时,CLR会执行验证过程,确保代码做的一切都是安全的(参数数量是否正确,参数类型是否正确,返回值是否被正确使用等等)。

Q10: 比较CLR, CTS和CLS.

A10: CLR是一个可以由多种编程语言使用的“运行时”, 它是围绕类型展开的,类型为应用程序和其他类型公开了功能,通过类型,可以用一种编程语言系的代码和另一种编程语言写的代码进行沟通,而CTS则是一个”通用类型系统”,它描述了类型的定义和行为。而由于CLR允许一种语言使用另一种语言定义的类型,但各种编程语言存在极大的区别,例如有些语言区分大小写而有些语言不区分,CLS是一个 ”公共语言规范”, 它定义了一个最小功能集,用一种语言定义了一种类型时,若想要其他语言可以使用该类型,就不要在该类型的public和protected成员中使用超出CLS的功能。每种编程语言都提供了CLR/CTS的一个子集以及CLS的一个超集。

(0)

相关推荐

  • C#之CLR内存字符串常量池(string)

    C#中的string是比特殊的类,说引用类型,但不存在堆里面,而且String str=new String("HelloWorld")这样的重装也说没有的. 我们先来看一个方法: class Program { static void Main(string[] args) { String s = "HelloWorld"; Console.WriteLine(s); } } 然后我们用ildasm.exe工具把它生成IL语言来看一看它里面是怎么玩的: .met

  • C#之CLR内存深入分析

    本文不再对值类型进行讨论,主要讨论一下引用类型.如要看内存值类型的朋友可以看一下前一篇C#之CLR内存原理初探. C#引用类型具体分析如下: 先来装备两个类: internal class Employee { public static Employee LookUp(string name) { return null; } public virtual string GetProgressReport() { return string.Empty; } } internal class

  • C# winform编程中响应回车键的实现代码

    本文介绍在使用C#进行窗体(WinForm)编程时,如何设置在窗口上按回车键的响应事件,或者说要响应按钮. 在窗体上按回车键,我们可以设置程序触发一些事件.这些事件都要通过窗体的AcceptButton这个属性来进行绑定. 在窗体的Load函数中,我们设置this.AcceptButton,这里的this表示是窗体对象本身.而AcceptButton即响应Enter回车键的按钮.它的值为当前窗体中的一个Button类型的控件的名称. 复制代码 代码如下: private void Form1_L

  • 基于C#实现的仿windows左侧伸缩菜单效果

    本文所述为基于C#实现的折叠菜单,风格仿照Windows打开我的电脑后左侧的伸缩菜单效果,并且同样是蓝色的效果,看着和windows的效果一样漂亮,可以实现折叠.展开等功能.这在学习C#界面编程的时候能用上,其主要实现代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq

  • 带着问题读CLR via C#(笔记二)类型基础

    Q1: Object类型包含哪些方法? A1: Object类型共包含6个方法,Equals, GetHashCode, ToString, GetType, MemberwiseClone和Finalize. Q2: new一个对象的过程是什么? A2: 1)计算对象所需字节数,包括该类型及其基类型定义的所有实例字段所需的字节数和类型对象指针.同步块索引所需字节数,类型指针和同步块索引是CLR用来管理对象的:2)在托管堆上分配该对象所需内存空间:3)初始化类型对象指针和同步块索引:4)执行构造

  • 重温C# clr 笔记总结

    1: .net framework 由两个部分组成:CLR 和 FCL. 2:在CLR中,所有错误都是通过异常来报告的. 3:智能感知功能主要是靠解析元数据实现的. 4:允许在不同语言之间方便的切换,并对各种语言进行紧密集成是CLR的出色特性. 5:一个方法只有在首次运行时才会由于jit造成一定的性能损失,以后对该方法的调用都以本地代码的形式全速运行. 6:方法签名指定了参数的数量(及其顺序),参数的类型:方法是否有返回值,如果有返回值,还要指定返回值的类型. 7:无论使用哪一种语言,类型的行为

  • C#之CLR内存原理初探

    本文初步讲述了C#的CLR内存原理.这里所关注的内存里面说没有寄存器的,所以我们关注的只有托管堆(heap),栈(stack), 字符串常量池(其中string是一个很特殊的对象) 首先我们看两个方法: void M1() { string name = "Tom"; M2(name); } void M2(string name2) { int length = 10; double rate = 10.0; name2 = "Joe"; return; } 这里

  • C#实现装箱与拆箱操作简单实例

    本文以一个简单实例讲述了C#装箱和拆箱操作的实现方法,简单来说装箱是将值类型转换为引用类型:拆箱是将引用类型转换为值类型,是涉及栈和堆的使用方面的东西,学过C#的人应该都知道,所以这里就不哆嗦了,本例代码也是面向C#新手的,非常简单. 具体实现代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace UnBoxing { class Program {

  • C# Pointer指针应用实例简述

    本文所述为在C#中使用Pointer指针的简单示例,非常适合新手参考学习.该实例演示了字符串的加密及解密的过程,将字符串指针p指向字符数组b,并将参数p传给函数,以及对给定字符串进行加密处理. 具体实例代码如下: using System; namespace PointerDemo { public class PointerDemo { public static void Main() { string s = "Hello Csharp!"; // 原字符串 Console.W

  • 带着问题读CLR via C#(笔记一)CLR的执行模型

    Q1: 什么是CLR? A1: CLR (Common Language Runtime) 是一个可以由多种编程语言使用的"运行时". Q2: CLR的核心功能有哪些? A2: 1)内存管理:2)程序集加载:3)安全性:4)异常处理:5)线程同步 Q3: CLR与使用的编程语言有关吗? A3: 无关.只要编译器是面向CLR的就行. Q4: 选用不同编程语言经过面向CLR的编译器编译后生成的结果相同吗? A4: 相同.无论选择什么语言,相应的编译器变异的结果都是一个托管模块,即一个标准的

  • 一篇文章带你深入理解JVM虚拟机读书笔记--锁优化

    目录 1. Java语言中的线程安全 1.1 不可变 1.2 绝对线程安全 1.3 相对线程安全 1.4 线程兼容 1.5 线程对立 2. 线程安全的实现方法 2.1 互斥同步 3. 锁优化 3.1 自旋锁与自适应自旋 3.2 锁消除 3.3 锁粗化 3.4 轻量级锁 3.5 偏向锁 总结 1. Java语言中的线程安全 按照线程安全的"安全程度"由强至弱来排序,可以将Java语言中各种操作共享的数据分为以下五类:不可变.绝对线程安全.相对线程安全.线程兼容和线程对立. 1.1 不可变

  • PHP curl模拟登录带验证码的网站

    需求是这样的,需要登录带验证码的网站,获取数据,但是不可能人为一直去记录数据,想通过自动采集的方式进行,如下是试验出来的结果代码!有需要的可以参考下! <?php namespace Home\Controller; use Think\Controller; class LoginController extends Controller { protected $cookieName = array('cookie_verify', 'cookie_verify'); protected $

  • python多进程读图提取特征存npy

    本文实例为大家分享了python多进程读图提取特征存npy的具体代码,供大家参考,具体内容如下 import multiprocessing import os, time, random import numpy as np import cv2 import os import sys from time import ctime import tensorflow as tf image_dir = r"D:/sxl/处理图片/汉字分类/train10/" #图像文件夹路径 da

  • 带大家深入了解Spring事务

    一.数据库事务简介 构成单一逻辑工作单元的操作集合称作事务(transaction).即使有故障,数据库系统也必须保证事务的正确执行--要么执行整个事务,要么属于该事务的操作一个也不执行.以资金转账为例,应该保证支票账户支出金额的操作和储蓄账户的存入金额的操作在同一个逻辑工作单元内完成.简言之,事务是访问并可能更新各种数据项的一个程序执行单元(unit). 二.事务的特性 数据库需要维护事务的以下四个性质: 1.原子性(Atomicity)事务是一个原子操作,由一系列动作组成.事务的原子性确保这

  • linux Shell学习笔记第三天

    第三天:条件选择 大 纲 应用实例分析 条件测试 if-else-fi case-in-esac 实现功能菜单: 执行脚本后 按1,显示当前时间 按2,显示CPU负载 按3,显示剩余内存 按0,退出脚本 按其他字符,提示超出选择范围后退出 分析步骤. #date +%T uptime awk截取 free –m 条件测试格式 #test –option obj #[ -option obj ] 返回结果 表达式内容测试结果是真的 表达式内容测试结果是假的 测试的对象分类 执行结果(执行成功或失败

  • javascript 学习笔记(六)浏览器类型及版本信息检测代码

    下面的checkBrowser()函数主要检测了三种浏览器(IE, firefox, chrome),其它的浏览器的检测有兴趣的朋友可以自行添加检测代码! HTML部分代码: (页面加载时执行检测函数) 复制代码 代码如下: <body onload="checkBrowser()"> <p id="userAgent"></p> <p id="browser"></p> </bo

  • Java并发之搞懂读写锁

    目录 ReentrantReadWriteLock 小结 StampedLock 小结 总结 ReentrantReadWriteLock 我们来探讨一下java.concurrent.util包下的另一个锁,叫做ReentrantReadWriteLock,也叫读写锁. 实际项目中常常有这样一种场景: 比如有一个共享资源叫做Some Data,多个线程去操作Some Data,这个操作有读操作也有写操作,并且是读多写少的,那么在没有写操作的时候,多个线程去读Some Data是不会有线程安全问

  • java基础详细笔记之异常处理

    目录 异常概述 常见异常的举例 空指针异常NullPointerException 数组角标越界异常ArrayIndexOutOfBoundsException 异常的抛出与捕捉 抛出异常 捕捉异常 在方法中抛出异常 使用throws关键字抛出异常 使用throw关键字抛出异常(自定义异常) 异常的使用原则 总结 异常概述 在Java中,这种在程序运行时可能出现的一些错误称为异常.异常是一个在程序执行期间发生的事件,它中断了正在执行的成宿的正常指令流. 视频笔记:  Java程序执行时遇到的异常

随机推荐

其他