zoukankan      html  css  js  c++  java
  • CLR的执行模型(4):执行程序集的代码

    一直觉得,一本书的第一章是一定要读通的,这样子才知道这本书适不适合自己。所以,对于第一章的内容,我就啰嗦一些了。

    托管程序集同时包含元数据和IL。IL是和CPU无关的机器语言,并且比大多数CPU语言都高级。IL能访问和操作对象类型,并且提供了创建和初始化对象的指令、调用对象上的虚方法以及直接操作数组元素。甚至实现了抛出和捕捉异常的指令,所以可将IL看成一种机器语言。

    为了执行方法,首先必须吧方法的IL转换成本机CPU指令。这是CLR的JIT的职责。

    下图展示了一个方法首次调用时候发生的事情:

    在Main方法执行之前,CLR会检查Main的代码所引用的所有类型。这导致CLR分配一个内部数据结构来管理对引用类型的访问。图中,Main方法引用了一个Console类型,导致CLR分配一个内部结构。在这个内部结构中,COnsole类型定义的方法都有一个对应记录项。每个记录项都含有一个地址,根据地址即可找到方法的实现。对这个结构初始化时,CLR将每个记录项都指向包含在CLR内部的一个未编档函数。我们将该函数成为JITComplier。

    Main方法首次调用WriteLine时,JITComplier函数会被调用。JITComplier函数负责将方法的IL代码编译成本机CPU指令。这个组件被称为JIT编译器或者JITter。

    JITCompiler函数被调用时,要知道调用的是哪个方法,以及具体是什么类型定义了该方法。然后JITCompiler会在定义程序集的元数据中查找被调用方法的IL。接着,JITCompiler验证IL代码,并将IL代码编译成本机CPU指令。本机CPU指令保存到动态分配的内存块中。然后,JITCompiler回到CLR为类型创建的内部数据结构,找到与被调用方法对应的那条记录,修改最初对JITCompiler的引用,使其指向内存块的地址,最后,JITCompiler函数跳转到内存块中的代码,既WriteLine方法的具体实现。代码完成并返回时,会回到Main中代码继续执行。

    然后Main要第二次调用WriteLine:

    第二次调用时,由于已对Write Line的代码进行了验证和编译,所以会直接执行内存块中的代码,完全跳过JITCompiler函数。执行完毕后会再次返回Main。

    所以方法仅在首次调用才有性能损失。

     在实际上,托管应用程序的性能是超越了非托管的。

    IL

    IL基于栈。也就是说,IL的所有指令都要将操作数压入一个执行栈,并从栈弹出执行结果。由于IL没有提供操作寄存器的指令,所以人们很容易创建新的语言和编译器,生成面向CLR的代码。此外,IL指令还是无类型的。

    IL的最大优势是程序的健壮性和安全性。将IL编译成本机CPU指令时,CLR会执行一个验证过程。这个过程会检查高级IL代码,确定代码所做的一切都是安全的。托管模块的元数据包含验证过程要用到的所有方法及类型信息。

    WIndows每个进程都有自己的虚拟地址空间。独立地址空间之所以必要,是因为不能简单地信任一个应用程序的代码:应用程序完全有可能读写无效的内存地址。每个Windows进程都放到独立的地址空间,获得鲁棒性和稳定性,让一个进程干扰不到另一个进程。

    但是,通过验证托管代码,可确保代码不会不正确地访问内存,不会干扰到另一个程序的代码。这样就可以将多个托管应用程序放到同一个Windows虚拟地址空间运行。

    CLR提供了一个在操作系统进程中执行多个托管应用程序的能力,每个托管应用程序都在一个AppDomain(应用程序域)中执行。妹妹个托管EXE文件默认都在它自己的独立空间中运行,这个地址空间只由一个应用程序域。

    不安全的代码

    C#编译器默认生成安全的代码。这种代码的安全性可以验证。然而,编译器也允许开发人员写不安全的代码,不安全代码通过直接控制内存地址,并可以操作这些地址处的字节。这种功能通常只有在与非托管代码进行互相操作,或者在某些算法中,才需要这样做。

    C#编译器要求包含不安全代码的所有方法都用unsafe关键字标记。除此以外,c#编译器要求使用/unsafe开关来编译源代码。

  • 相关阅读:
    那么 Appium 到底是怎么工作的呢?
    最小的 Velocity 教程
    CentOS 7 使用经验(更新中)
    [TL-WR841N V5~V9] 如何当作无线交换机使用?
    VS2012打包部署Winform程序
    ASP.NET 应用程序生命周期概述[转自MSDN]
    (翻译)从底层了解ASP.NET体系结构 [转]
    .NET在IE9中页面间URL传递中文变成乱码的解决办法
    终于把你必须知道的.NET看完了
    装箱与拆箱的操作与内存管理
  • 原文地址:https://www.cnblogs.com/renzhoushan/p/10353195.html
Copyright © 2011-2022 走看看