欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#之CLR内存深入分析

程序员文章站 2024-02-19 22:37:58
本文不再对值类型进行讨论,主要讨论一下引用类型。如要看内存值类型的朋友可以看一下前一篇c#之clr内存原理初探。 c#引用类型具体分析如下: 先来装备两个类:...

本文不再对值类型进行讨论,主要讨论一下引用类型。如要看内存值类型的朋友可以看一下前一篇c#之clr内存原理初探

c#引用类型具体分析如下:

先来装备两个类:

internal class employee
{
 public static employee lookup(string name)
 {
  return null;
 }

 public virtual string getprogressreport()
 {
  return string.empty;
 }
}

internal class manager : employee
{
 public override string getprogressreport()
 {
  return string.empty;
 }
}

employee类里有一个虚方法getprogressreport和一个静态方法lookup,manager类继承了employee并重写了getprogressreport.

static void main(string[] args)
{
 employee e = new manager();
 e = e.lookup("tom");
 e.getprogressreport();
}

 我们在main里面写上这样的代码,再来对照着下图看看栈和堆是怎么运作的。

C#之CLR内存深入分析

 当jit编译器将这些il代码转换成本地cpu指令时,会注意到所有的类型:employee,manager,string(由于tom字符串).

1.当运行方法之前,"prologue"代码会为这些对象在内存中开辟空间。

2.employee e=new manager();会把e压入栈,然后保存manager对象地址,我们在初级篇的时候说过,每个对象都有一个同步块索引和类型对象指针,这个指针就是内存的地址。

C#之CLR内存深入分析

3.e=employee.lookup("tom");调用一个静态方法时,clr会定位与定义静态方法的类型对应的类型对象。然后jit编译器在类型对象的方法表中查找与被调用的方法对应的记录项,对方法进行jit编译(如果需要的话),再调用jit编译的代码。这个时候我们知道loopup返回的是employee对象(这时,我们一开始创建的manager对象还不确认有没有被清除,因为gc会自动去清理这些托管代码),所以在堆上面开辟一个employee的内存块并把e的地址改变成employee对象所在的位置。 

注意:employee和manager类型对象都包含了“类型指针对象”成员。这时由于类型对象本质上也是对象。clr创建类型对象时,必须初始化这些成员。初始化成什么呢?clr开始在一个进程中运行时,会立即为mscorlib.dll中定义的system.type类型创建一个特殊的类型对象。employee和manager类型对象都是该类型的”实例“。 因此,它们的类型对象指针成员会初始化成对system.type类型对象的引用。

顺便说一句object.gettype返回的就说”类型指针对象“所存储的地址。

C#之CLR内存深入分析