好吧,废话少说,先上一章Hello World图:

我们有了一个Hello world程序,如此之简单,再加上我今天没有用汉字编程o(>﹏<)o,所以一切很简单明了。

故事开始:

编译:

一个程序写完肯定要编译,以前什么C啊什么的都是编译成本机的CPU指令,但是我们的C#不是。

C#,VB.NET都会把它们编译成托管模块,托管模块在一个标准的可移植的PE文件中。(那些懵懂的少年肯定慌了,这是什么鬼,又是托管模块又是PE文件的。莫慌,所有你听不懂的高大上的术语其实都很简单,你现在不需要懂,听我慢慢道来)

所谓PE文件,就是可移植执行体,简单来讲就是.EXE和.DLL这种鬼东西(这个exe和C语言生成的有区别的)。这个PE文件里的托管模块,你可以当做一个对象,对象里有四个属性,一个PE头(描述文件),一个CLR头(描述这个对象的整体的一些信息,比如main入口),元数据(这个很关键,一种元数据表包含源代码中定义的那些那些类型和成员的描述信息,另一种包含引用的类型和成员的描述信息),IL代码(就是你的源代码被编译后的代码,又称中间语言)。

如果觉得麻烦,前面两个属性你可以忘掉了,记住后面两个就好:元数据和IL代码(简单来讲,就是代码的描述信息和编译后的代码)。

但是一个PE文件可不只一个托管模块,它可以由几个托管模块组成。编译器会把多个托管模块和资源文件合并成一个包含清单的程序集,这才是最后的PE文件。

运行:

但是这个托管模块也就是PE文件并不能直接运行,他需要CLR。

CLR常用简写词语,CLR是公共语言运行库(Common Language Runtime)和Java虚拟机一样也是一个运行时环境,它负责资源管理(内存分配和垃圾收集等),并保证应用和底层操作系统之间必要的分离。CLR存在两种不同的翻译名称:公共语言运行库和公共语言运行时。

此描述及以后的描述均来自百度百科,我懒得手打。

CLR的核心功能包括:内存管理,程序集加载,安全性,异常处理和线程同步。

这个东西又称为公共语言运行时。

前面的说到不能直接运行的时候,这里有懵懂的少年肯定说,我生成的exe文件明明可以直接运行。

这是因为你的电脑上安装了.NET Framework。当你在打开exe程序的时候你的进程的主线程会调用MSCorEE.dll的一个方法,这个方法会初始化CLR,再加载exe程序集,然后调用入口方法即main函数。

所以说实际上你的代码运行是需要在CLR上的。

那么CLR到底是怎么玩我们的Hello world的?

它会在运行时编译我们的IL代码。(先别吐槽为什么要编译两次,后面有讲)

早在Main函数执行之前,CLR就会检测Main的代码所引用的所有类型,然后生成了一个内部的数据结构来管理引用类型的访问。

在这个内部结构中,每个类型比如Console的每个方法都会有一个入口,每个入口都有一个地址(这里叫地址A吧),这个地址A就可以找到方法的实现代码。

而在这个内部数据结构初始化的时候,所有的这些入口的地址都会被设置成一个叫JITCompiler的函数。

就比如上面图中的hello world代码第一句,CLR在执行这句代码的时候会跑进JITCompiler这个函数中,这是内部操作:

  1. 会跑进托管模块,然后根据元数据匹配类名和方法名,获取你要执行的Console这个类里面Writeline这个函数在IL代码里面的地址B。
  2. 然后编译这段IL代码变成本机的CPU指令放到一块内存空间中,地址为C。(在这个编译之前还会进行验证哦,验证这个IL代码是否安全)
  3. 接着修改元数据中地址A的值变为地址C的值。
  4. 最后跳转到地址C开始执行地址C的cpu指令。

那么如果我们第二次去执行Writeline函数呢?此时内部结构中Writeline函数入口的地址指向的已经是编译好的CPU指令的地址了,所以也就不会去执行JITCompiler这个函数。

千万不要认为这样一定会很慢哦,除了第一次运行时JITCompiler的编译可能需要花费掉编译和优化的时间,后来执行的就是本地CPU指令哦。再加上JITCompiler的这个编译会根据你的机器的CPU不同可能会去生成一些专属于本CPU的特殊指令去优化IL代码,有的这种托管程序可能还要比非托管程序快。

好了,本章的精髓就是上面这些了。

现在我们想想为什么要编译两次?

因为这样的话,无论用C#、VB、F#这些东西你都可以生成一样的包含IL代码的托管程序集,然后这个托管程序集在CLR上运行,也就是说可以混合写代码,一个C#代码可以调用VB代码的DLL,用最适合的语言做最适合的事情。

并且在CLR监视之下执行的IL代码因为在执行前会进行安全校验,所以会提高程序的健壮性和可靠性。

【C#进阶系列】01 CLR的执行模型——一个Hello World的故事的更多相关文章

  1. 01.由浅入深学习.NET CLR 基础系列之CLR 的执行模型

    .Net 从代码生成到执行,这中间的一些列过程是一个有别于其他的新技术新概念,那么这是一个什么样的过程呢,有什么样的机制呢,清楚了这些基本的东西我们做.Net的东西方可心中有数.那么,CLR的执行模型 ...

  2. 01.CLR的执行模型

    在非托管的C/C++中,可以进行一些底层的操作     "公共语言运行时"(CLR)是一个可由多种编程语言使用的"运行时"          CLR的核心功能包 ...

  3. C#进阶系列 ---- 《CLR via C#》

      [C#进阶系列]30 学习总结 [C#进阶系列]29 混合线程同步构造 [C#进阶系列]28 基元线程同步构造 [C#进阶系列]27 I/O限制的异步操作 [C#进阶系列]26 计算限制的异步操作 ...

  4. JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

    本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 ■ 跨浏览器事件处理 □ 事件必须在页面元素加 ...

  5. JavaScript进阶系列01,函数的声明,函数参数,函数闭包

    本篇主要体验JavaScript函数的声明.函数参数以及函数闭包. □ 函数的声明 ※ 声明全局函数 通常这样声明函数: function doSth() { alert("可以在任何时候调 ...

  6. CLR 的执行模型(2)

    第一章 CLR 的执行模型(2) 本篇内容大纲 Framework 类库(Framework Class Library , FCL) 通用类型系统(Common Type System,CTS) 公 ...

  7. 第一章 CLR 的执行模型

    CLR via C# 读书笔记:第一章 CLR 的执行模型(1) 第Ⅰ部分CLR基础.这部分为三章(第一章:CLR的只想能够模型,第二章:生成.打包.部署和管理应用程序及类型,第三章:共享程序集和强命 ...

  8. [.NET MVC4 入门系列01]Helloworld MVC 4 第一个MVC4程序

    [.NET MVC4 入门系列01]Helloworld MVC 4 第一个MVC4程序   一.练习项目: http://www.asp.net/mvc/tutorials/mvc-4/gettin ...

  9. 第一部分 CLR基础:第1章 CLR的执行模型

    1.1将源代码编译成托管模块

随机推荐

  1. 转:ecshop商品分类页获取相册列表方法

    ecshop商品分类页获取相册列表方法 很久之前就看到过你好在商品列表页有获取到相册列表,但是一直没有实践过,感觉应该挺简单的吧,但是最近手上的项目刚好就需要这个功能,然后就想到网上查下资料,至少找个 ...

  2. Asp.net Core WebApi 使用Swagger做帮助文档,并且自定义Swagger的UI

    WebApi写好之后,在线帮助文档以及能够在线调试的工具是专业化的表现,而Swagger毫无疑问是做Docs的最佳工具,自动生成每个Controller的接口说明,自动将参数解析成json,并且能够在 ...

  3. Target runtime com.genuitec.runtime.generic.jee50 is not defined

    导入别人的工程,发现报错Target runtime com.genuitec.runtime.generic.jee50 is not defined   解决方法:1. 找到工程目录的.setti ...

  4. spring mvc jsp运行不起来的问题

    spring mvc已经处理成让jsp运行,即: <bean class="org.springframework.web.servlet.view.InternalResourceV ...

  5. 前端经常使用插件使用文档 以及demo

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  6. centos 7 中 tomcat 安装

    一. 安装 jdk [root@iZm5ei4m ~]# /usr/local/tomcat/bin/startup.sh 一.安装 jdk 二.设置环境变量 #################### ...

  7. JAVA IO NIO

    http://www.cnblogs.com/handsome1013/p/4882862.html http://www.cnblogs.com/dolphin0520/ http://www.cn ...

  8. 关于IT概念的一些思考

    同事提及“软件工程.软件生命周期.项目管理.CMMI.IPD.RUP.UML及UML建模.面向对象分析与设计.需求分析.系统分析与设计……等等,它们到底是什么?它们之间有什么关系?”   下面是个人见 ...

  9. android手机出现sqlite3 not found的解决方法

    解决方法如下: 1.如果/system目录为不可读写的,需要挂载为读写: C:\Users\easteq>adb shell root@android:/ # mount -o remount, ...

  10. [原]Android打包之Gradle打包

    最近尝试了一下Android的Gradle打包,发现确实比Ant打包会方便很多,特此记录下来. 注:android的gradle现在插件的版本已经是0.14.3了,对于一些老的方法和api,有一些已经 ...