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

.net垃圾回收-原理浅析

2019-11-17 02:30:19
字体:
来源:转载
供稿:网友
.net垃圾回收-原理浅析

本文引自:http://www.VEVb.com/wilber2013/p/4357910.html

在开发.NET程序过程中,由于CLR中的垃圾回收(garbage collection)机制会管理已分配的对象,所以程序员就可以不用关注对象什么时候释放内存空间了。但是,了解垃圾回收机制还是很有必要的,下面我们就看看.NET垃圾回收机制的相关内容。

创建对象

在C#中,我们可以通过new关键字创建一个引用类型的对象,比如下面一条语句。New关键字创建了一个Student类型的对象,这个新建的对象会被存放在托管堆中,而这个对象的引用会存放在调用栈中。(对于引用类型可以查看,C#中值类型和引用类型)

Student s1 = new Student();

在C#中,当上面的Student对象被创建后,程序员就可以不用关心这个对象什么时候被销毁了,垃圾回收器将会在该对象不再需要时将其销毁。

当一个进程初始化后,CLR就保留一块连续的内存空间,这段连续的内存空间就是我们说的托管堆。.NET垃圾回收器会管理并清理托管堆,它会在必要的时候压缩空的内存块来实现优化,为了辅助垃圾回收器的这一行为,托管堆保存着一个指针,这个指针准确地只是下一个对象将被分配的位置,被称为下一个对象的指针(NextObjPtr)。为了下面介绍垃圾回收机制,我们先详细看看new关键字都做了什么。

new关键字

当C#编译器遇到new关键字时,它会在方法的实现中加入一条CIL newobj命令,下面是通过ILSpy看到的IL代码。

IL_0001: newobj instance void GCTest.Student::.ctor()

其实,newobj指令就是告诉CLR去执行下列操作:

  • 计算新建对象所需要的内存总数
  • 检查托管堆,确保有足够的空间来存放新建的对象
    • 如果空间足够,调用类型的构造函数,将对象存放在NextObjPtr指向的内存地址
    • 如果空间不够,就会执行一次垃圾回收来清理托管堆(如果空间依然不够,就会报出OutofMemoryException)
  • 最后,移动NextObjPtr指向托管堆下一个可用地址,然后将对象引用返回给调用者

按照上面的分析,当我们创建两个Student对象的时候,托管堆就应该跟下图一致,NextObjPtr指向托管堆新的可用地址。

托管堆的大小不是无限制的,如果我们一直使用new关键字来创建新的对象,托管堆就可能被耗尽,这时托管堆可以检测到NextObjPtr指向的空间超过了托管堆的地址空间,就需要做一次垃圾回收了,垃圾回收器会从托管堆中删除不可访问的对象

应用程序的根

垃圾回收器是如何确定一个对象不再需要,可以被安全的销毁?

这里就要看一个应用程序根(application root)的概念。根(root)就是一个存储位置其中保存着对托管堆上一个对象的引用,根可以属性下面任何一个类别:

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