MyObject obj = new MyObject();
我知道'new'关键字将调用构造函数并在托管堆中初始化对象。
我的问题是 CLR 如何执行以下操作。
- CLR如何执行上述行?
- CLR如何为对象分配内存?
- CLR如何确定对象的大小?
- 如果没有空间为堆中的对象分配内存,CLR 将如何知道它?
MyObject obj = new MyObject();
我知道'new'关键字将调用构造函数并在托管堆中初始化对象。
我的问题是 CLR 如何执行以下操作。
当创建引用类型(类、委托、接口、字符串或对象)时,它被分配到堆上。Net 有四个不同的堆:(gen0、gen1、gen2)(小对象堆)和 LOH(大对象)堆)。根据创建时间(从 gen0 到 gen1 到 gen2 等),所有 85k 或更小的东西都放在前三个堆之一。大于 85k 的对象被放置在 LOH 上。LOH 永远不会被压缩,所以最终,我正在做的类型的分配最终会导致 OOM 错误,因为对象分散在该内存空间中。这些被称为托管堆。
要创建一个对象,您需要做的就是使用 new 关键字;.NET 将负责创建、初始化对象并将其放置在正确的堆上,并保留任何必要的额外内存。之后,您几乎可以忘记该对象,因为完成后您不必删除它。
当您使用 new 关键字创建引用类型对象时,它被放置在堆上,并且它的引用主要用于当前正在运行的堆栈中。还有其他可能的来源,您的对象可以用作参考:
这 5 个实际上是 GC 根节点,从中形成对象引用层次结构。想象一下经典的 Customer 类,它通常有一个存储 Order 类的集合。当一个 Order 被添加到 order 集合中时,集合本身会保存对添加的 order 的引用。如果 Customer 类的实例也有对它的堆栈引用。
这就是复杂对象的层次结构的形成方式,这就是 GC 查看引用的方式。
例如。客户对象的堆栈引用-> 对订单列表对象的引用-> 引用单个订单。
任何从这 5 个根中松散引用的东西都容易发生 GC。
如何将内存分配给对象有点复杂,并且它通常随着 MKK 的指定而随时间增长http://msdn.microsoft.com/en-us/magazine/cc163791.aspx
一个简单的例子可能是:
class MyClass
{
string Test="Hello world Wazzup!";
byte[] data=new byte[86000];
}
很容易假设分配时 MyClass 的大小包括:
• 19 个字符
• 86,000 字节。
事实上,对象的大小将只包括一般类的东西,以及存储对象指向字符串和字节数组(类级变量)所需的内存,然后将它们分别分配到堆上。字符串将在 SOH 上分配,其对象引用由类的实例持有;字节数组将被分配到 LOH,因为它大于 85 KB。
SOH 可以被压缩,里面不会有碎片,而 LOH 可以在内存中有碎片。
问候。