一个天真的类型系统会将对象存储为指向其类型的指针(其中包含许多有用的信息,如vtable,对象大小等),后跟其数据.如果.Net具有这样的类型系统,则object在32位系统上占用4个字节,在64位上占用8个字节.
我们可以看到它没有.对象开销是两个指针大小,另外,还有一个指针大小的"最小"大小.
那么object在幕后实际存储的内容是什么?
是的,这就是它的样子.'type handle',又名'方法表指针'在偏移0处,对象数据在偏移量4处跟随.在offset-4处有一个额外的字段,名为'syncblock'.它就在那里,因为它还在未使用对象空间时参与垃圾收集堆,这是一个需要两个指针的双链接空闲块列表.不要让它浪费,syncblock有几个用途,比如存储锁状态,存储哈希码,当需要存储太多时,存储指向显式同步块的指针.
最小的可能对象是盒装字节,4 + 4 + 1 = 9字节.但GC堆的分配粒度是4个字节,因此您将得到4,12个字节的下一个倍数.
使用Visual Studio中的调试器,这一切都非常明显.你会在这个答案中找到提示.
(这些都来自Microsoft Shared Source CLI ;它具有CLR的源代码.)
如果你看一下clr\src\vm\object.h,你会看到:
// The generational GC requires that every object be at least 12 bytes in size.
#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader))
Run Code Online (Sandbox Code Playgroud)
这是非常明显的.此外,clr\src\vm\gcscan.cpp你可以看到如下的陈述
_ASSERTE(g_pObjectClass->GetBaseSize() == MIN_OBJECT_SIZE);
Run Code Online (Sandbox Code Playgroud)
要么
_ASSERTE(totalSize < totalSize + MIN_OBJECT_SIZE);
Run Code Online (Sandbox Code Playgroud)
我认为这解释了为什么你会看到意想不到的物体尺寸.:)
更新:
@Hans在同步块上有一个很好的观点; 我只是想指出一个微妙的,再次记录在object.h:
/* Object
*
* This is the underlying base on which objects are built. The MethodTable
* pointer and the sync block index live here. The sync block index is actually
* at a negative offset to the instance. See syncblk.h for details.
*/
class Object
{
protected:
MethodTable* m_pMethTab;
//No other fields shown here!
};
Run Code Online (Sandbox Code Playgroud)
请注意这一部分:
同步块索引实际上是实例的负偏移量.
因此,同步块显然实际上并不遵循方法表(正如汉斯所提到的那样),但它在它之前 - 因此它不是对象的"正常"部分(因为缺少更好的单词).
| 归档时间: |
|
| 查看次数: |
656 次 |
| 最近记录: |