zoukankan      html  css  js  c++  java
  • 托管程序的执行(图)

    为了执行一个方法,首先必须把它的IL转换成本地CPU指令。这是CLR的JIT(just-in-time或者“即时”)编译器的职责。

    图1-4

     
    图1-4方法的首次调用 
         就在Main方法执行之前,CLR会检测出Main的代码引用的所有类型。这导致CLR分配一个内部数据结构,它用于管理对所引用的类型的访问。在图1-4中,Main方法引用了一个Console类型,这导致CLR分配一个内部结构。在这个内部数据结构中,Console类型定义的每个方法都有一个对应的记录项( entry 翻译成“记录项”,其他译法还有条目、入口等等。虽然某些 entry 包含了一个地址,所以相当于一个指针,但并非所有 entry 都是这样的。在其他 entry 中,还可能包含了文件名、类型名、方法名和位标志等信息。)。每个记录项都容纳了一个地址,根据此地址即可找到方法的实现。对这个结构进行初始化时,CLR将每个记录项都设置成(指向)包含在CLR内部的一个未文档化的函数。我将这个函数称为JITCompiler。
          Main方法首次调用WriteLine时,JITCompiler函数会被调用。JITCompiler函数负责将一个方法的IL代码编译成本地CPU指令。由于IL是“即时”(justintime)编译的,所以通常将CLR的这个组件称为JITter或者JIT编译器。 注意:如果应用程序在Windows的x86版本或WoW64中运行,JIT编译器将生成x86指令。如果应用程序以一个64位应用程序的形式在Windows的x64或Itanium版本上运行,那么JIT编译器将分别生成x64或 IA64指令。 
    JITCompiler函数被调用时,它知道要调用的是哪个方法,以及具体是什么类型定义了该方法。然后,JITCompiler会在定义(该类型的)程序集的元数据中查找被调用的方法的IL。接着,JITCompiler验证IL代码,并将IL代码编译成本地CPU指令。本地CPU指令被保存到一个动态分配的内存块中。然后,JITCompiler返回CLR为类型创建的内部数据结构,找到与被调用的方法对应的那一条记录,修改最初对JITCompiler的引用,让它现在指向内存块(其中包含了刚才编译好的本地CPU指令)的地址。最后,JITCompiler函数跳转到内存块中的代码。这些代码正是WriteLine方法(获取单个String参数的那个版本)的具体实现。这些代码执行完毕并返回时,会返回至Main中的代码,并跟往常一样继续执行。 
          现在,Main要第二次调用WriteLine。这一次,由于已对WriteLine的代码进行了验证和编译,所以会直接执行内存块中的代码,完全跳过JITCompiler函数。WriteLine方法执行完毕之后,会再次返回Main。 
    图1-5展示了第二次调用WriteLine时发生的事情。

      一个方法只有在首次调用时才会造成一些性能损失。以后对该方法的所有调用都以本地代码的形式全速运行,无需重新验证 IL 并把它编译成本地代码。

      JIT 编译器将本地 CPU 指令存储到动态内存中。一旦应用程序终止,编译好的代码也会被丢弃。所以,如果将来再次运行应用程序,或者同时启动应用程序的两个实例(使用两个不同的操作系统进程),JIT  编译器必须再次将 IL 编译成本地指令。

  • 相关阅读:
    Aurora 数据库支持多达五个跨区域只读副本
    Amazon RDS 的 Oracle 只读副本
    Amazon EC2 密钥对
    DynamoDB 读取请求单位和写入请求单位
    使用 EBS 优化的实例或 10 Gb 网络实例
    启动 LAMP 堆栈 Web 应用程序
    AWS 中的错误重试和指数退避 Error Retries and Exponential Backoff in AWS
    使用 Amazon S3 阻止公有访问
    路由表 Router Table
    使用MySQLAdmin工具查看QPS
  • 原文地址:https://www.cnblogs.com/shenfengok/p/2171959.html
Copyright © 2011-2022 走看看