CLR要求对象必须使用new运算符创建,在使用new运算符创建一个对象时具体都做了些什么呢?

1.计算所有定义的实例字段,所有的基类型包括System.Object需要分配的字节数。

每一个堆上的对象还需要两个额外的成员:类型对象指针同步块索引,CLR使用它们来管理对象。它们两个需要的字节数算在对象的大小里面。

2.从托管堆分配对象需要的字节数(也就是给对象分配内存)。所有的字节置为0

3.初始化类型对象指针同步块索引

4.调用实例构造器。大多数编译器自动生成调用基类构造器的代码。最终会调用Sytem.Object的构造器,这个构造器方法什么也不做,只是return。

在new执行完上面的操作以后,返回一个新创建的对象的引用,这个引用保存在实例对象变量里。如:A a=new A();   保存在变量a里。

is和as运算符

//o是一个Object对象    Employee是一个类
if(o is Employee)
{Employee e=(Employee)o;...
}

上面的代码是关于is非常典型的应用,这里CLR会进行两次类型 检查:①is运算符检查   ②执行强转的时候检查。CLR的类型检查提高了安全性,同时也会消耗一部分性能。C#提供了as运算符来简化代码并且改善性能。

Employee  e=o as Employee;
if(e!=null)
{//...
}

这里CLR会检查o的类型是否兼容Employee,如果兼容则返回Employee对象的引用,否则返回null。这里只执行了一次类型检查

运行时类型,对象,线程堆栈,托管堆之间的联系

当创建一个线程时,会分配1M的堆栈空间,用来向方法传递参数以及存放定义在方法里面的局部变量。堆栈的建造是从高位内存地址向地位内存地址进行。下面演示一个线程执行调用M1方法的过程:

M1方法执行时,首先会在堆栈上为name变量分配内存:

接着M1调用M2方法,将name局部变量作为参数参数传递,name变量的地址进栈:

接着会执行M2方法,首先还是给length和tally两个局部变量从堆栈上分配内存:

M2执行到return语句,返回到M1,继续执行。

调用静态方法,实例方法以及虚方法之间的不同

internal  class Employee
{  public          Int32     GetYearsEmployed()     { ...  }  public  virtual String     GetProgressReport()  { ...  }  public  static   Employee   Lookup(String  name)  { ...  }
}  internal  sealed  class Manager : Employee
{  public  override  String     GetProgressReport()  { ...  }
}

加入代码接着调用M3方法,M3方法包含的代码阐释了CLR的运行原理(一般可能不这样写代码)

上图展示CLR载入到进程,托管堆初始化。

当JIT编译器将M3的IL代码编译为本地CPU指令时,CLR会保证定义这些类型的程序集加载。使用程序集的元数据,CLR这些类型的信息并创建一些数据结构来呈现类型本身。关于Employee和Manager类型展示如下:

(Int32和String是常用的类型,这里没有展示)

1.在定义一个类型时,可以定义一个静态数据字段,存放类型对象本身的内存分配的字节数。每一个类型对象里面是一个包含每个方法入口的方法表,这里的Employee定义了GetYearsEmployed , GetProgressReport, 和Lookup三个方法,所以在Employee的方法表里面有三个入口。在CLR确定了所有的方法被创建并编译之后,线程开始执行M3的CPU指令。同样,这里会为M3方法的局部变量分配内存,(初值为0或null)。

2.接着M3执行构造器创建Manager对象,

3.接着执行下面的代码,M3调用静态方法Lookup。当调用静态方法时,JIT编译器会定位到跟定义静态方法相对应的类型对象。然后,JIT编译器定位到方法表的入口处。Lookup方法在堆上构造了一个Manager对象并且返回该对象的地址。保存在变量e中,此时e不再指向开始new出来的那个Manager对象,开始的Manager对象已经没有变量引用它。在未来某个时候GC会对它进行回收。

4.接着M3调用非虚方法的实例方法GetYearsEmployed,CLR会定位到与变量e类型一致的对象。(如果Employee没有定义该方法,JIT编译器会向上一层层查找直到Object。)

然后JIT编译器定位到对象的方法表,这里可以看出相对于静态方法多了一步定位。编译该方法(如果之前没有编译过),调用编译后的代码。

5.接着M3调用虚方法实例方法GetProgressReport,调用时,JIT会生成一些额外的代码,这些代码在每一次方法调用时都会执行,它会首先会查找发起调用的变量,然后跟随地址来调用对象。这里的e变量执行了Manager对象,生成的额外的代码会检查对象内部的类型对象指针,该指针成员引用了实际的对象的类型。然后定位到对象的方法表,接着编译。

注   《CLR via C#》(Jeffrey Richter著)——.NET 界的经典之作,读的过程写点笔记跟大家分享,我也推荐大家看英文版,能够直接领会原意  

转载于:https://www.cnblogs.com/mszhangxuefei/archive/2012/07/24/clrnotes-4.html

new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系相关推荐

  1. C++运行时类型信息 (RTTI)

    dynamic_cast 用于多态类型的转换 typeid typeid 运算符允许在运行时确定对象的类型 type_id 返回一个 type_info 对象的引用 如果想通过基类的指针获得派生类的数 ...

  2. C++知识点54——RTTI(运行时类型识别)

    一.RTTI概述 RTTI的功能由两个运算符实现,一个是typeid,用来返回表达式的类型:另一个是dynamic_cast,作用是将基类的指针或引用安全地转为子类的指针或引用 二.typeid ty ...

  3. C++ Primer 5th笔记(chap 19 特殊工具与技术)运行时类型识別RTTI

    1. 运行时类型识别(run-time type identification ) 当我们将这两个运算符用于某种类型的指针或引用, 并且该类型含有虚函数时, 运算符将 使用指针或引用所绑定对象的动态类 ...

  4. 如何在运行时确定对象类型(RTTI)

    RTTI 是"Runtime Type Information"的缩写,意思是:运行时类型信息.它提供了运行时确定对象类型的方法.本文简略介绍 RTTI 的一些背景知识.描述 RT ...

  5. C++-运行时类型信息,异常(day11)

    一.运行时类型信息 1.typeid运算符 头文件:#include<typeinfo> C++的标准头文件,都对应相应的类 //sizeof(类型/变量/表达式),返回内存大小 type ...

  6. 白话C++系列(27) -- RTTI:运行时类型识别

    http://www.cnblogs.com/kkdd-2013/p/5601783.html RTTI-运行时类型识别 RTTI:Run-Time Type Identification. 那么RT ...

  7. [面试] C/C++ 语法(六)—— RTTI(运行时类型信息)

    RTTI(RunTime Type Information),顾名思义,对象运行时类型信息,以便在运行时进行类型识别. C++ 的对象识别可通过以下三个技术得以实现: (1)dynamic_cast ...

  8. C++ 学习笔记之(19) new、delete表达式、RTTI(运行时类型识别)、枚举、类成员指针、嵌套类、局部类、位域、volatile、extern C

    C++ 学习笔记之(19) new.delete表达式.RTTI(运行时类型识别).枚举.类成员指针.嵌套类.局部类.位域.volatile.extern C C++ 学习笔记之(19) new.de ...

  9. 【TS】1552- 浅谈TS运行时类型检查

    What-什么是运行时类型检查? 编译时类型检查(静态类型检查): 在编译阶段对变量类型进行静态检查,编译后的代码不保留任何类型标注信息,对实际代码运行没有影响 运行时类型检查(动态类型检查): 在代 ...

最新文章

  1. Apache如何将HTTP重定向到HTTPS
  2. 前端:收集前端开发者手边必备的11款神器
  3. drools动态配置规则_基于 Flink 和 Drools 的实时日志处理
  4. DrawerLayout 使用
  5. 怎么把照片做成计算机主题,windows10主题制作怎么操作_windows10电脑主题如何自己制作...
  6. unity 世界坐标间角度_Unity 世界坐标局部坐标下的旋转
  7. Zabbix官方文档以及日常运维
  8. Discuz手机模板:NVBING5-APP手机版
  9. nubia/努比亚Z5Sn(32GB) root教程_方法
  10. 【STM32】HAL库在7针脚0.96寸OLED屏上的移植---硬件SPI(一)
  11. ffmpeg ——下载与安装
  12. 用计算机制作微课教学教案,微课教案设计
  13. 2022育婴员(五级)判断题及答案
  14. win732位升级64位教程
  15. Soul应用提取聊天记录【2021年中】
  16. R语言rhdf5读写hdf5文件(.h5)展示文件组织结构和数据索引
  17. 织梦dedecms TAG标签调用汇总
  18. Java判断身份证号码是否正确
  19. 元器件符号的认识和原理图
  20. 内容社交产品中的关键数据——获得良好反馈的用户比例

热门文章

  1. linux高编IO-------opendir、closedir、readdir
  2. rocksdb学习笔记
  3. DELPHI下的SOCK编程(转)
  4. 说给做管理软件的同行:你们得学会职业规划
  5. Android onSaveInstanceState、onRestoreInstanceState保存数据
  6. android LinkedList的基本用法
  7. sklearn应用—高斯混合
  8. RabbitMQ—重复消费、数据丢失和消息顺序性
  9. 数据结构和算法-链表
  10. BZOJ 2134: 单选错位