• clrvia,初读CLR Via C# :CLR,托管模块,程序集,Main方法的运行过程


    1,CLR(Common Language Runtime)公共语言运行时,是可被多种语言所同时使用,并且很多特性可用于所有针对它的开发语言。我们所编写的程序在编译的同时由编译器进行语法的检查和代码分析,然后生成一个托管模块。

    2,

    托管模块是由一个标准的32位Microsoft Windows 可执行体(PE32)文件或者是一个标准的64位Microsoft Windows 可执行体(PE32+)文件,以上两种的其中一种再加上CLR头信息(包含使该模块成为托管模块的一些信息,如:CLR的版本,托管模块的方法入口点(我们俗称的Main方法等))再加上元数据(这里的元数据并不是我们的源代码文件,是每个托管模块所包含的元数据表,一种类型表、一种源代码引用类型、成员表)最后再加上IL代码(就是由我们各个语言的编译器所编译出来的中间语言代码),在最后运行的时候,CLR控制IL代码的运行。

    3,

    写到这里大家可能觉得CLR是和托管模块一起工作的吧?其实不是,CLR只和程序集(assembly)一起工作。又来一个概念,什么是程序集?
    程序集是一个或者多个由资源文件、模块组成的逻辑性分组。程序集在整个程序中的重用和版本控制都是最小的单元。程序集是怎么形成的呢?当我们通过图1.1所示的过程把源代码文件通过各种语言的编译器编译成托管模块(中间语言和元数据)之后,再加上我们程序中需要的一些jpge、gif等资源文件交由生成程序集的工具进行处理之后,成为与CLR打交道的程序集(默认情况下,生成程序集的工具由编译器来完成,但不一定是编译器)

    4,

    让我们看看CLR到底是如何让我们所写的代码跑起来的。

     不管我们的源文件是什么语言写的C#或者VB再或者J#这些都不重要,最终我们的语言会通过相对的编译器被编译成IL中间语言
      1,把我们的main方法编译成IL中间语言,然后再转换成本地的CPU指令(这一步是由JIT(just-in-time或者“即时”)编译器完成的)。那么在执行main方法之前,CLR会检测main方法的代码所有的类型,然后生成一个数据结构表,记录方法的类型、参数引用等一些信息,以便对引用类型的信息进行访问,这个时候Console类中的所有方法都已经记录在CLR生成的数据结构表中并有每个方法的内存地址。然而,在第一次调用Console.WriteLine方法的时候,JIT编译器就知道要调用哪个方法,然后JIT将IL编译成CPU指令,然而这个CPU指令就被分配在一个动态内存中,以便第二次调用的时候直接调用已经编译好的CPU指令,而省去了再编译的麻烦。注意:这里所说的再编译,是指应用程序一直在运行的时候,不需要再编译一次Console.WriteLine方法,而是直接运行。如果程序退出,将再一次对方法进行检验和编译。

    那么再次总结以下方法调用的过程:
    1、 当程序第一次运行时,会调用JIT编译器,它可以知道调用了那些方法,以及通过CLR生成的数据结构表找到定义该方法的类和具体实现;
    2、 然后JIT编译器在元数据中找到该方法的IL代码,进行验证,然后转换成CPU指令。并分配在动态内存中;
    3、 JIT编译器将调用的方法地址改为第二步的内存地址;
    4、 跳转到上Main方法编译后的代码。
    5、 执行完毕并返回
    当程序第二次执行的时候,就不需要JIT的验证,而是直接调用本地CPU的指令。

  • 相关阅读:
    《架构之美》阅读笔记六
    《架构之美》阅读笔记五
    软件工程——个人总结
    软件工程——团队作业4
    软件工程——团队答辩
    软件工程-团队作业3
    软件工程——团队作业2
    软件工程-团队作业1
    软件工程第二次作业——结对编程
    软件工程第一次作业补充
  • 原文地址:https://www.cnblogs.com/lihfeiblogs/p/lihfeiblogs.html
Copyright © 2020-2023  润新知