由值类型分配在GC堆中引发的血案

   首先,声明一个观点:
   所有值类型的实例或者包含在线程栈上,或者包含在GC堆上。所有的引用类型在GC堆或者  LOH上创建。
以前觉得值类型总在线程栈上面。值类型被分配在GC堆中的原因是,如果值类型是一个对象的一个字段的话,那么就分配在堆中。

  在.NET中,引用类型的实例即一个对象,到底是怎么样的呢?
 
 

.NET本质论中的一个对象是三个部分,一个Syncblk(同步索引块)一个Typehandle(类型句柄)和对象的实例字段,而MSND的一片文章中说可以分成四部分,最后一个部分是string的实例字段的特殊引用表,我觉得这个更确切一些,因为在.NET中字符串是驻留的,并且可以跨应用程序域的,所以一个对象中的string一定是特殊的处理的。

 同步索引块:4字节
 类型句柄: 4字节
 空类型会有个额外的分配:4字节
总计:4+4+4=12字节

值类型用sizeof()就可以,引用类型暂时还没有办法获得,目前我没有找到,除了Marsh.sizeof 方法。

一般所说的对象头只包含Sync Block,而不包含TypeHandle。

SyncBlock有什么用呢?
内容:
    Syncblk共有有5个位标志,其中一个位标志是为GC保留的,它标识对象是否是“可到达对象“(“可到达对象“是垃圾回收算法里的一个名词,简单的说就是指正在被应用程序使用的对象)。剩余的27个位作为一个索引,被称作syncindex,它指向一个表(CRL内部的同步索引块)。

作用:
    Syncblk的主要功能是用于对象的锁定,即线程安全,本质上用到了系统的临界区域块,因为系统的临界区域块的某个引用只能被同一个线程访问,而CRL中的对象如果引用了这个块,就可以实现线程锁定访问。
    在CRL中,一般该对象的这个区域是0,当用lock语句或者Monitor等操作的时候,CRL会将其关联到CRL的一个临界区域数组,操作完成,在取消对其引用。



TypeHandle
  Typehandle主要用于引用到该对象的类型。
  .NET中其实就是一个名字为 CORINFO_CLASS_STRUCT的数据结构,C#和C++中不同,C#中每一个对象只有一个对应的方法表。 CORINFO_CLASS_STRUCT中的方法表中的方法并不直接指向方法,而是指向 一个叫做stub routine的入口,这个入口指向的 不是某段代码,而是 JIT ,具体代码的位置要等 JIT 来给定。如下面的图,来自MSDN


上面的每个方法槽的入口都是 call Pre-JIT Stub xxx。

对于虚方法, CLR 是把虚方法和一般方法分开来放的,两种方法的入口项不一样,方便子类对虚方法进行索引。虚方法的入口操作码不是 call ,而是 callvirt


参考文档:
http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值