MyObject obj = new MyObject();

我知道'new'关键字将调用构造函数并初始化托管堆中的对象。

我的问题是CLR如何执行以下操作。
  • 上一行如何由CLR执行?
  • CLR如何为对象分配内存?
  • CLR如何确定对象的大小?
  • 如果没有空间为堆中的对象分配内存,那么CLR怎么会知道呢?
  • 最佳答案

    创建引用类型(类,委托(delegate),接口(interface),字符串或对象)时,会将其分配到堆上。.Net具有四个不同的堆:(gen0,gen1,gen2)(小对象堆)和LOH(大对象)堆)。大小等于或小于85k的所有内容都会在前三个堆中的一个上进行,具体取决于创建时间(从gen0到gen1到gen2等)。大于85k的对象将放置在LOH上。 LOH永远不会被压缩,因此最终,我正在做的类型的分配最终将导致OOM错误,因为对象会分散在该内存空间中。这些被称为托管堆。

    要创建一个对象,您需要做的就是使用new关键字。 .NET将负责在正确的堆上创建,初始化和放置对象,并保留任何必要的额外内存。之后,您几乎可以忘记该对象,因为完成该对象后不必删除它。

    使用new关键字创建引用类型对象时,该对象将放置在堆上,并且其引用通常在当前运行的堆栈中使用。还有其他可能将您的对象用作引用的来源:

  • 全局/静态对象引用
  • CPU寄存器
  • 对象的最终确定引用(更多内容)
  • Interop引用(传递给COM/API调用的.NET对象)
  • 堆栈引用(主要在此处使用)

  • 这5个实际上是GC的根节点,在这些根节点上形成了对象引用层次结构。想象一下经典的Customer类,该类通常具有一个存储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可以在内存中具有碎片。

    问候。

    关于c# - 当我给MyObject obj = new MyObject()时会发生什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11027155/

    10-17 00:04