首页 > 学院 > 开发设计 > 正文

.NET对象的创建、垃圾回收、非托管资源的手动处理

2019-11-17 02:34:19
字体:
来源:转载
供稿:网友

.NET对象的创建、垃圾回收、非托管资源的手动处理

本篇用来梳理对象的创建、垃圾的回收,以及非托管资源的手动处理。

→首先运行应用程序,创建一个Windows进程。

→CLR创建一块连续的虚拟地址空间,这个地址空间就是托管堆。而且,这个地址空间最初并没有对应的物理存储空间。

虚拟地址空间分成2段。一个区段是普通堆,也叫GC堆,大小小于85000字节的引用类型对象的实例被分配在这里;另一个是大对象堆,大小大于等于85000字节的引用类型对象的实例被分配在这里。

对于客户端应用程序,每个区段的大小大致是16MB;对于服务端应用程序,每个区段的大小大致是64MB。另外,每个区段的大小还会因CPU的数量,是否是32位或64位操作系统而各异。

随着每个区段被装满对象,CLR会分配更多的区段,直到整个进程空间都满了为止,每个进程可使用4GB的内存。

托管堆上维护着一个指针NextObjPtr,指向下一个对象在托管堆上分配的位置。

托管堆根据存储信息的不同分为垃圾回收堆GC Heap和加载堆Loader Heap。垃圾回收堆GC Heap存储对象实例,受GC管理;加载堆Loader Heap存储AppDomain中的元数据信息,例如基类型、静态字段、静态方法、接口信息等,不受GC管理,它的生命周期从创建AppDomain开始到卸载AppDomain结束。此时,托管堆以及其它方面大致是这样分布的:

1

→在托管堆上创建对象

□ 引用类型对象创建

使用new关键字创建引用类型对象。

FileStream fs = new FileStream(@"",FileMode.Open);

以上代码经编译器编译,在生成的中间IL代码中实际上是一个newobj指令。IL相关的指令还包括:ldstr指令用于创建string类型对象,newarr用于分配新的数组对象,box指令用于在值类型转换为引用类型时,将值类型字段拷贝到托管堆上。

通过以下代码来体会托管堆上创建对象的大致过程:

public class Employee
{
    PRivate int _id;
    private Status _status;
    public Employee()
    {
        _id = 1;
        _status = new Status();
    }
}
public class Sales : Employee
{
    public bool _isLive;
    public bool IsLive()
    {
        return _isLive;
    }
    public static void Main()
    {
        Sales _sales;
        _sales = new Sales();
        _sales._isLive = true;
        Console.WriteLine(_sales.IsLive());
    }
}
public class Status
{
    private int _years;
    private char _level = "A";
}

1、执行Sales _sales,在线程堆栈上开辟4byte的内存空间,用于保存Sales对象的托管堆地址,此时为null。

2、_sales = new Sales(),递归

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表