理解垃圾回收平台的基本工作原理

每个程序都有使用不同的资源,比如文件、内存缓冲、屏幕空间、网络连接、数据库连接等,其实在面上对象的程序设计中,每个类型都代表可供程序使用的一种资源,

要使用这些资源就必须为这些资源类型分配内存。下面是访问一种资源所需的步骤:

(1)  调用IL指令的newobj,为代表资源的类型分配内存,在c#中使用new操作符,编译器就会自动生成该指令。

(2)  初始化资源,设置资源的初始状态,使资源可用。类型的实例构造器负责这个工作。

(3)  访问类型成员来使用资源。

(4)  摧毁资源状态以进行清理。

(5)  释放内存。垃圾回收器负责这一步。

看是如此简单的过程,有多少程序员忘记释放不再需要的内存?又有多少程序员试图调用已释放的内存?

进行非托管编程时,应用程序的这两种bug比其它bug严重很多,一般都无法预测到他们的后果,如果是其它bug,可以发现程序行为异常来修正。但是这两种bug会造成资源泄露和对象损坏,是应用程序表现不可预测。

通常进行资源管理很难而且很枯燥。它会极大分散开发人员的注意力,使之无法专注要真正解决的问题。要是有一种机制能为开发人员简化这个工作,那是一件不错的事情,幸好有这中机制,这就是垃圾回收(简称GC –garbage collection).

有了GC使的开发人员的到解放,就不必跟踪内存的使用,也不必知道什么时候释放内存。但是垃圾回收对内存中的类型资源一无所知。这意味着GC不知道怎么执行前面的第四步:摧毁资源状态以进行清理 。为了使资源得到正确的清理,开发人员必须编写知道如何正确清理资源的代码。这些代码通常放在Finalize,Dispose和close方法中,但是GC提供了一些帮助,使得开发人员大多数时候可以跳过第四步。

另外要注意,值类型、集合类型、String、Attribute、Delegate和Exception所代表的资源无需进行特殊清理。

如果一个类型代表非托管和本地资源(比如文件、数据库连接、套接字、mutex、位图和图标等),那么在对象准备回收时,必须进行一些清理代码。

2、从托管堆中分配资源

CLR要求所有托管代码的资源在托管堆中分配。这个堆和C运行时的堆非常相似,只是你永远不要从托管堆中删除对象(应用程序不需要的对象会自动删除),这就引出一个问题:托管堆如何知道应用程序不需要一个对象?

目前有好多种垃圾回收器的算法,不同算法都针对不同环境进行优化,已提供这种环境下最佳的性能。本系列将关注Microsoft.NET Framework的CLR所采用的垃圾回收算法。

前面说到new负责创建一个对象,导致编译器生成一个newobj指令。该指令会导致CLR执行以下步骤。

(1)  计算类型(以及所有基类型)资源所需要的字节数。

(2)  加上对象开销所需的字节数。每个对象都有两个字节的开销:一个是类型对象指针和一个同步块索引(可能不同资料上面名字翻译不一样,以后章节中再对这两种不同的开销做讲解,你也可以去MSDN网站上查一些资料),真对32位应用程序和64位应用程序分配的字节是不一样的。

(3)  CLR检查保留区域是否能提供分配对象所需的字节数,如果托管堆有足够的空间对象会被放进去,这里有个NextObjPtr指针,该对象是在这个指针指向的地址放入的。并且为他分配的字节数就会清零,接着调用类型实例构造器,IL指令newobj会返回对象的地址。在返回地址之前,NextObjPtr指针的值会加上对象占据的字节数,这样会得到一个新值,他指向下一个对象放入托管堆得地址。

                

              

为了对比,让我们看一下C运行时堆如何分配。在C运行时堆中,为对象分配内存要遍历一个数据结构组成的链表。一旦发现有足够大的块,那个块就会被拆分,同时修改链表节点的指针,以确保链表的完整性。对于托管堆,分配对象只需要在指针上加一个值,这个显然明显快得多。事实上,托管堆分配对象的速度几乎可以与从线程栈分配内存媲美。另外,大多数堆(包含C运行时堆)都是在他们找到可用空间的地方分配,所以连续创建几个对象,有可能被分散。中间相隔数MB的地址空间。但是在托管堆中连续分配对象能够确保他们对象的地址是连续的。

综合上诉,似乎托管堆得实现的简单行和速度方面远远优于C运行时堆。但是这有个特别注意的细节你的搞清楚,托管堆之所以有这么多好处,是因为它做了一个相当大胆的假设:“地址空间和存储是无限的”。这个假设简直荒谬之极。所以托管堆必须通过某种机制来允许它这么假设。这种机制就是垃圾回收。

应用程序调用new创建对象时,可能没有足够的地址空间来分配该对象,托管堆将需要的字节加到NextObjPtr指针中的地址上来检查这种情况。如果结果值超过了地址的末尾,表明托管堆已满,必须进行垃圾回收了。

备注:本系列文章来自<<CLR via C#>>第三版

时间: 2024-08-04 12:21:38

理解垃圾回收平台的基本工作原理的相关文章

垃圾回收机制的优点和原理

垃圾回收机制的优点和原理:Java 语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理. 由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域".垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存. 垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不

垃圾回收机制的优点和原理,并考虑两种回收机制

垃圾回收机制的优点和原理,并考虑两种回收机制 1.  java的一个显著的特点就是引入了垃圾回收机制,使c++程序员最头痛的内存管理问题迎刃而解,它使得java管理员在编写程序的时候不需要考虑内存管理,因为有了垃圾回收机制: 2. java对象中不再有“作用域”的概念,只有对象的引用才有“作用域”. 3. 垃圾回收机制可以有效的防治内存泄露,有效的使用可以使用的内存. 4. 垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收

一篇文章教会你理解Scrapy网络爬虫框架的工作原理和数据采集过程

今天小编给大家详细的讲解一下Scrapy爬虫框架,希望对大家的学习有帮助. 1.Scrapy爬虫框架 Scrapy是一个使用Python编程语言编写的爬虫框架,任何人都可以根据自己的需求进行修改,并且使用起来非常的方便.它可以应用在数据采集.数据挖掘.网络异常用户检测.存储数据等方面. Scrapy使用了Twisted异步网络库来处理网络通讯.整体架构大致如下图所示. Scrapy爬虫框架 2.由上图可知Scrapy爬虫框架主要由5个部分组成,分别是:Scrapy Engine(Scrapy引擎

[CLR via C#]21. 自动内存管理(垃圾回收机制)

目录 理解垃圾回收平台的基本工作原理 垃圾回收算法 垃圾回收与调试 使用终结操作来释放本地资源 对托管资源使用终结操作 是什么导致Finalize方法被调用 终结操作揭秘 Dispose模式:强制对象清理资源 使用实现了Dispose模式的类型 C#的using语句 手动监视和控制对象的生存期 对象复活 代 线程劫持 大对象 一.理解垃圾回收平台的基本工作原理 值类型(含所有枚举类型).集合类型.String.Attribute.Delegate和Event所代表的资源无需执行特殊的清理操作.

Clr Via C#读书笔记---垃圾回收机制

#1 垃圾回收平台的基本工作原理: 访问一个资源所需的具体步骤: 1)调用IL指令newobj,为代表资源的类型分配内存.在C#中使用new操作符,编译器就会自动生成该指令.2)初始化内存,设置资源的初始状态,使资源可用.类型的实例构造器负责设置该初始状态.3)访问类型的成员(可根据需要反复)来使用资源.4)摧毁资源的状态以进行清理.正确清理资源的代码要放在Finalize, Dispose和Close方法.5)释放内存.垃圾回收器独自负责这一步. 托管堆如何知道应用程序不再用一个对象? 托管堆

Java GC(垃圾回收)的工作原理

Garbage Collection简称GC,是垃圾回收的意思. 内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃.Java语言提供的GC功能可以自动检测对象是否超过作用域,从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法,资源回收工作全部交由GC来完成,程序员不能精确控制垃圾回收的时机. 下面简要介绍一下GC在实现垃圾回收时的基本工作原理. Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放.对于程序员来说,

Java垃圾回收机制的工作原理

Java垃圾回收机制的工作原理 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 一.Java中引入垃圾回收机制的作用 当我们建完类之后,创建对象的同时,进行内存空间的分配,为了防止内存空间爆满,java引入了垃圾回收机制,将不再引用的对象进行回收,释放内存,循环渐进,从而防止内存空间不被爆满. 1.垃圾回收机制的工作原理 创建的对象存储在堆里面,把堆比喻为院子中的土地,把对象比喻为土地的管理者,院子比喻为java虚拟机,当创建一个对象时,java虚拟机将给

.Net 垃圾回收机制原理(一)

英文原文:Jeffrey Richter 编译:赵玉开 链接:http://www.cnblogs.com/yukaizhao/archive/2011/11/23/dot_net_GC_1.html 有了Microsoft.Net clr中的垃圾回收机制程序员不需要再关注什么时候释放内存,释放内存这件事儿完全由GC做了,对程序员来说是透明的.尽管如此,作为一个.Net程序员很有必要理解垃圾回收是如何工作的.这篇文章我们就来看下.Net是如何分配和管理托管内存的,之后再一步一步描述垃圾回收器工作

Unity优化方向——优化Unity游戏中的垃圾回收

介绍 当我们的游戏运行时,它使用内存来存储数据.当不再需要该数据时,存储该数据的内存将被释放,以便可以重用.垃圾是用来存储数据但不再使用的内存的术语.垃圾回收是该内存再次可用以进行重用的进程的名称. Unity使用垃圾回收作为管理内存的一部分.如果垃圾回收发生得太频繁或者有太多工作要做,我们的游戏可能会表现不佳,这意味着垃圾回收是导致性能问题的常见原因. 在本文中,我们将了解垃圾回收如何工作的,什么时候发生垃圾回收,以及如何有效地使用内存,从而最小化垃圾回收对游戏的影响. 诊断垃圾回收的问题 垃