眨眼间我已经实习了半年时间并且转正了,身份也正式从一个学生转变为一个职场人,这个博客自从开始实习以来就一直没有更新过= =没错,就是我懒癌晚期,不过不行!一切都要开始走向正轨,此博会继续见证我的成长,从现在开始吧!

最近刚开始看CLR via C#这本神作,本来以为自己会看不懂,之前我对这本书一直是“远观不可亵玩”的态度,当真正看了之后才发现许多事木有有你想象的那么难嘛~好,开始正文。

CLR,又叫通用语言运行时,又叫Common Language Runtime,你可以把他看作是一个虚拟机。来,咱先来看一个很经典的.NET Framework结构图:

我们按照层级关系一层层来看

第一层:

我们最熟悉的编程语言,.NET目前已经支持超过70中编程语言了,只要是.NET支持的编程语言都能享受CLR所带来的便利和优势。

第二层和第三层一起讲:

汇编器,这里的编译器指的不是通常意义的编译器,通常意义指的编译器是指可以直接将高级语言转换成目标机器语言,而这里的汇编器指的是将.NET支持的编程语言编译成托管代码(第三层)。那么问题来了。。。托管代码是什么鬼?可以这么理解,如果说.NET编译器生成的是托管代码,那我们平时学习的C/C++,编译器生成的就是非托管代码。托管代码包含IL和元数据(我擦。。。怎么又多了两个名词),IL指的是微软定义的中间语言(MSIL,Microsoft Intermediate Language,你可以理解为从高级语言到目标机器语言中间的一种代码)。CLR必须知道代码中的数据类型、类和他引用的类型和类的定义才能加载代码、管理内存、执行方法,所以这些信息就叫做metadata。所以第二道第三层的过程就简单的理解为把高级语言编译成中间语言即可。

第四层:

在这一层,CLR提供了运行时非常重要的一个环节即将中间语言编译成目标机器语言的功能。这里我们举个例子再来看一幅图深入讨论一下:

上图展示了一个方法首次调用时发生的事情,在Main方法执行之前,CLR会检测出Main代码所有的引用类型。CLR就会构造像右边那样的一个数据结构,里面是一些方法中用到的引用。这里存着每一个方法的入口,比如Console类中有WriteLine(),WriteLine(string)等,然后CLR会将其进行初始化,将这些入口指向一个未编档函数。这个函数就是JITCompiler。

当Main方法首次调用WriteLine时,JITCompiler会被调用,首先JIT会先申请一块稍后会用到的内存块,然后JITCompiler会在程序集的元数据中找到被调用方法的IL,并将将IL编译成本机的目标代码放入事先分配好的内存当中,接着JIT会修改最初调用它的这个引用指向之前分配好的内存并执行它,最后JIT会回到源代码继续执行下一条语句。这样一来,当Main方法之后再访问这个方法时就会直接去调用本机代码。所以这也是c#到底属于解释型还是编译型语言之争的源头,因为他是在执行的时候才去生成最终的目标代码的。讲到这里,许多人要开始质疑了,托管代码在运行时多了JIT这一步,而非托管代码是直接执行的目标代码,这效率肯定差一大截吧?事实并非如此,微软已经把JIT对性能的影响降到了最低,下面列举了托管代码由于非托管代码的一些地方:

  1. 当JIT生成本地代码时会根据当前硬件环境去使用当前cpu最优的指令,简单的来说就是根据不同cpu会做代码优化。
  2. JIT在代码运行时能够检测到代码运行的情况并分析进一步优化代码,比如CLR检测到一个if分支在99%的情况下是true,那么JIT就会重新编译,达到进一步的代码优化。(这一点据说还没有完全实现?有待考证,有知道的可以评论)

嗯。。今天要讲的差不多讲完了

初识CLR的更多相关文章

  1. CLR学习之初识CLR

    一.什么是CLR? CLR即公共语言运行时(Common Language Runtime,简称CRL),就是微软为.net产品构建的运行环境,与java的JVM类似,通俗的讲就是.net虚拟机.CL ...

  2. Python开发【第一篇】:初识Python

    初识python 一.python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解 ...

  3. Python开发【第二篇】:初识Python

    Python开发[第二篇]:初识Python   Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏 ...

  4. CLR via C#(16)--泛型

    泛型就像是一个模板,常常定义一些通用的算法,具体调用时再替换成实际的数据类型,提高了代码的可重用性. 一.初识泛型 1. 简单实例 以最常用的FCL中的泛型List<T >为例: stat ...

  5. CLR via C#(14)-可空值类型,关于?和??的故事

    我们都知道,值类型是不能为Null的,但是在实际应用中有些情形却需要将值类型置为null.因此,CLR中引用了可空值类型的用法.今天的文章中见到最多的符号估计就是?了吧. ?——初识可空值类型 1.  ...

  6. CLR via C# 提纲

    第I部分 CLR基础第1章 CLR的执行模型 31.1 将源代码编译成托管模块 31.2 将托管模块合并成程序集 61.3 加载公共语言运行时 81.4 执行程序集的代码 101.4.1 IL和验证 ...

  7. [CLR via C#]17. 委托

        回调函数是一种非常有用的编程机制,它已经存在很多年了.Microsoft .NET Framework通过委托(delegate)来提供一种回调机制.不同于其他平台(比如非托管C++)的回调机 ...

  8. C#脚本引擎 CS-Script 之(一)——初识

    最近在做新产品,这个产品需要满足不同项目对于系统的定制性数据处理需求,比如有的要统计一段时间内某开关打开关闭了多少次,有的要统计一段时间内空调的使用率,有的希望根据温度来控制空调的开还是关,有的则是希 ...

  9. Python初识与简介【开篇】

    目录 1.扯淡 2.Python历史 3.Python简介 4.Python应用 5.为什么是python而不是其他语言? 6.Python的种类 7.Python的特点 8.Python设计哲学 9 ...

随机推荐

  1. DataTables列过滤器

    var table = $('#example').DataTable(); table.columns().flatten().each( function ( colIdx ) { // Crea ...

  2. 蚁群算法matlab实现

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang 以下用matlab实现蚁群算法:   %蚂蚁算法test   %用产生的一个圆上的十个点来检验蚂蚁 ...

  3. ios如何判断键盘是否已经显示

    ios如何判断键盘是否已经显示   在群里看到有人问:ios如何判断键盘已经显示在界面上. 其实这个解决很简单: 写一个单例来管理键盘的状态. 这个单例在初始化方法init种监听2个事件,分别是 UI ...

  4. Gradle Android客户端程序打包(基于gradle 2.10版本验证通过)

    一.前言 目前正在准备从eclipse开发环境向AndroidStudio迁移,提前过去探探路,不出所料,原来gradle脚本果然报错,无法运行,想想索性把本地的gradle一起升级到最新版本,毕竟1 ...

  5. KEIl混合编程步骤详解

    一.在keil中C函数调用汇编函数: 主要思路:先用C来编写所要实现及调用的汇编函数,然后由此C函数生成相应的汇编代码,这样我们就可以不用去管混合编程调用时复杂的函数接口,我们只要修改相应汇编函数中的 ...

  6. 2015第23周四HTML特殊字符显示问题

    1.项目中常采用EL表达式来输出后台内容,但测试发现它并不能完美处理要输出内容包含有<>或&等HTML特殊字符问题.先直接给出此问题JSTL的解决方案: 1.引入标签:<%@ ...

  7. Redhat6.4 配置本地网络的FTP YUM源

    Redhat6.4 配置本地网络的FTP YUM源 如果本机IP: 192.168.8.47 (一) 配置本机的yum源 使用以下的方法能够配置本机的yum源: 1) scp命令上传ISO文件到: / ...

  8. File类的基本操作之InputStream字节输入流

    话不多少,我直接把代码贴上来了.有什么问题请给我留言 package org.mark.streamRW; import java.io.File; import java.io.FileInputS ...

  9. [Cycle.js] Fine-grained control over the DOM Source

    Currently in our main() function,  we get click$ event. function main(sources) { const click$ = sour ...

  10. Android模仿jquery异步请求

    01 package com.xbl.task; 02   03 import java.io.BufferedReader; 04 import java.io.InputStream; 05 im ...