http://topic.csdn.net/t/20051005/15/4308139.html
我们都知道,CLR保存程序中的数据,程序员可以控制的有两个地方:保存引用对象实例的堆和保存值类型和对象引用的堆栈。如下面的代码
public void MethodA()
{
int intValue = 123; // 在堆栈中建立了一个Int32类型变量
System.Text.StringBuilder sb = new StringBuilder(); // 建立了一个类实例引用
System.Text.StringBuilder sb2 = sb; // 建立第二个类引用,指向第一个类实例
}
从上面能够看出,在代码中建立了三个变量,一个是Int32整数类型变量,两个是StringBuilder类实例引用变量,他们同时指向保存在CLI堆中的同一个堆实例。
我们能发现,当这个名为“MethodA”的方法执行完毕后,这三个变量本身,还有他们指向的数据本身都将被抛弃,如果这个方法有返回值,那么,这个值所引用的数据将被保留。
所以我怀疑,指向CLR堆中类型实例的引用,它在.Net内部可能也是一种类型,有可能是一个struct(结构),因为结构是值类型,所以可以存放在速度快的堆栈中,因为它是一种结构,对象引用变量有与值类型变量同样的特性,在方法内部定义的引用除非方法返回值返回,否则方法执行结束后自动销毁,在方法的不同区块中定义的对象引用不能运行在区块外面,这明显是堆栈的后进先出特性。如
public void MethodB()
{
int i = 123;
try
{
StringBuilder sb = new StringBuilder();
}
finally
{
// ...
}
i = 456; // 这时,重新使用i变量可以的
sb.Append( "... "); // 在这里使用try块中的定义变量就不行
}
所以我觉得对象引用实际上在CLR中被表示成一个自动指针一样的东西,他是一个结构,而这个结构具体保存了哪些数据微软没有公布,不过至少有几点,首先是指向对象实例入口地址的指针,这是肯定的,还有就是.Net中有GC,为了保证GC执行,.Net中保存在CLR堆中的所有对象实例数据里面都有一个固定大小的对象头,里面包含了一些信息,如对象引用,对象执行接口表之类。这个对象头的入口地址肯定也在这个对象引用里面。另外就是当前对象引用的实例具体在内存中的大小,多少字节等。
有了这些东西,实际上我们操作对象引用,如方法返回值,方法参数对象等,不过就是类似于
int i = 123;
int j = i;
这样的赋值操作,当前上面我写的是Int32类型,引用类型也同样。
另外,我怀疑GC在执行垃圾收集的时候,就是扫描所有堆栈内的这些引用对象的结构,然后再用一些算法去除指向同一个对象实例的结构,那么剩下来的结构的个数就是CLR堆内对象实例的个数,然后剩下来的对象实例就是没有被引用的对象实例,自然就可以安全的被删除了。