文档章节

垃圾回收

孙本新
 孙本新
发布于 2015/06/04 17:45
字数 2199
阅读 5
收藏 0

Lua5.2采用垃圾回收机制对所有的lua对象(GCObject)进行管理。Lua虚拟机会定期运行GC,释放掉已经不再被被引用到的lua对象。 基本算法

基本的垃圾回收算法被称为"mark-and-sweep"算法。算法本身其实很简单。

首先,系统管理着所有已经创建了的对象。每个对象都有对其他对象的引用。root集合代表着已知的系统级别的对象引用。我们从root集合出发,就可以访问到系统引用到的所有对象。而没有被访问到的对象就是垃圾对象,需要被销毁。

我们可以将所有对象分成三个状态:

White状态,也就是待访问状态。表示对象还没有被垃圾回收的标记过程访问到。
Gray状态,也就是待扫描状态。表示对象已经被垃圾回收访问到了,但是对象本身对于其他对象的引用还没有进行遍历访问。
Black状态,也就是已扫描状态。表示对象已经被访问到了,并且也已经遍历了对象本身对其他对象的引用。

基本的算法可以描述如下:

[plain] view plaincopyprint?

当前所有对象都是White状态;  
将root集合引用到的对象从White设置成Gray,并放到Gray集合中;  
while(Gray集合不为空)  
{  
    从Gray集合中移除一个对象O,并将O设置成Black状态;  
    for(O中每一个引用到的对象O1) {  
        if(O1在White状态) {  
            将O1从White设置成Gray,并放到到Gray集合中;  
        }  
    }  
}  
for(任意一个对象O){  
    if(O在White状态)  
        销毁对象O;  
    else  
        将O设置成White状态;  
}  

Incremental Garbage Collection 上面的算法如果一次性执行,在对象很多的情况下,会执行很长时间,严重影响程序本身的响应速度。其中一个解决办法就是,可以将上面的算法分步执行,这样每个步骤所耗费的时间就比较小了。我们可以将上述算法改为以下下几个步骤。

首先标识所有的root对象: [plain] view plaincopyprint?

当前所有对象都是White状态;  
将root集合引用到的对象从White设置成Gray,并放到Gray集合中;  

遍历访问所有的gray对象。如果超出了本次计算量上限,退出等待下一次遍历: [plain] view plaincopyprint?

<p>while(Gray集合不为空,并且没有超过本次计算量的上限)</p>{  
    从Gray集合中移除一个对象O,并将O设置成Black状态;  
    for(O中每一个引用到的对象O1) {  
        if(O1在White状态) {  
            将O1从White设置成Gray,并放到到Gray集合中;  
        }  
    }  
}  

销毁垃圾对象:

[plain] view plaincopyprint?

for(任意一个对象O){  
    if(O在White状态)  
        销毁对象O;  
    else  
        将O设置成White状态;  
}  

在每个步骤之间,由于程序可以正常执行,所以会破坏当前对象之间的引用关系。black对象表示已经被扫描的对象,所以他应该不可能引用到一个white对象。当程序的改变使得一个black对象引用到一个white对象时,就会造成错误。解决这个问题的办法就是设置barrier。barrier在程序正常运行过程中,监控所有的引用改变。如果一个black对象需要引用一个white对象,存在两种处理办法:

将white对象设置成gray,并添加到gray列表中等待扫描。这样等于帮助整个GC的标识过程向前推进了一步。
将black对象该回成gray,并添加到gray列表中等待扫描。这样等于使整个GC的标识过程后退了一步。

这种垃圾回收方式被称为"Incremental Garbage Collection"(简称为"IGC",Lua所采用的就是这种方法。使用"IGC"并不是没有代价的。IGC所检测出来的垃圾对象集合比实际的集合要小,也就是说,有些在GC过程中变成垃圾的对象,有可能在本轮GC中检测不到。不过,这些残余的垃圾对象一定会在下一轮GC被检测出来,不会造成泄露。 Lua5.2采用垃圾回收机制对所有的lua对象(GCObject)进行管理。Lua虚拟机会定期运行GC,释放掉已经不再被被引用到的lua对象。 基本算法

基本的垃圾回收算法被称为"mark-and-sweep"算法。算法本身其实很简单。

首先,系统管理着所有已经创建了的对象。每个对象都有对其他对象的引用。root集合代表着已知的系统级别的对象引用。我们从root集合出发,就可以访问到系统引用到的所有对象。而没有被访问到的对象就是垃圾对象,需要被销毁。

我们可以将所有对象分成三个状态:

White状态,也就是待访问状态。表示对象还没有被垃圾回收的标记过程访问到。
Gray状态,也就是待扫描状态。表示对象已经被垃圾回收访问到了,但是对象本身对于其他对象的引用还没有进行遍历访问。
Black状态,也就是已扫描状态。表示对象已经被访问到了,并且也已经遍历了对象本身对其他对象的引用。

基本的算法可以描述如下:

[plain] view plaincopyprint?

当前所有对象都是White状态;  
将root集合引用到的对象从White设置成Gray,并放到Gray集合中;  
while(Gray集合不为空)  
{  
    从Gray集合中移除一个对象O,并将O设置成Black状态;  
    for(O中每一个引用到的对象O1) {  
        if(O1在White状态) {  
            将O1从White设置成Gray,并放到到Gray集合中;  
        }  
    }  
}  
for(任意一个对象O){  
    if(O在White状态)  
        销毁对象O;  
    else  
        将O设置成White状态;  
}  

Incremental Garbage Collection 上面的算法如果一次性执行,在对象很多的情况下,会执行很长时间,严重影响程序本身的响应速度。其中一个解决办法就是,可以将上面的算法分步执行,这样每个步骤所耗费的时间就比较小了。我们可以将上述算法改为以下下几个步骤。

首先标识所有的root对象: [plain] view plaincopyprint?

当前所有对象都是White状态;  
将root集合引用到的对象从White设置成Gray,并放到Gray集合中;  

遍历访问所有的gray对象。如果超出了本次计算量上限,退出等待下一次遍历: [plain] view plaincopyprint?

<p>while(Gray集合不为空,并且没有超过本次计算量的上限)</p>{  
    从Gray集合中移除一个对象O,并将O设置成Black状态;  
    for(O中每一个引用到的对象O1) {  
        if(O1在White状态) {  
            将O1从White设置成Gray,并放到到Gray集合中;  
        }  
    }  
}  

销毁垃圾对象:

[plain] view plaincopyprint?

for(任意一个对象O){  
    if(O在White状态)  
        销毁对象O;  
    else  
        将O设置成White状态;  
}  

在每个步骤之间,由于程序可以正常执行,所以会破坏当前对象之间的引用关系。black对象表示已经被扫描的对象,所以他应该不可能引用到一个white对象。当程序的改变使得一个black对象引用到一个white对象时,就会造成错误。解决这个问题的办法就是设置barrier。barrier在程序正常运行过程中,监控所有的引用改变。如果一个black对象需要引用一个white对象,存在两种处理办法:

将white对象设置成gray,并添加到gray列表中等待扫描。这样等于帮助整个GC的标识过程向前推进了一步。
将black对象该回成gray,并添加到gray列表中等待扫描。这样等于使整个GC的标识过程后退了一步。

这种垃圾回收方式被称为"Incremental Garbage Collection"(简称为"IGC",Lua所采用的就是这种方法。使用"IGC"并不是没有代价的。IGC所检测出来的垃圾对象集合比实际的集合要小,也就是说,有些在GC过程中变成垃圾的对象,有可能在本轮GC中检测不到。不过,这些残余的垃圾对象一定会在下一轮GC被检测出来,不会造成泄露。 http://www.brpreiss.com/books/opus5/html/page424.html

本文转载自:http://blog.csdn.net/yuanlin2008/article/details/8558103

共有 人打赏支持
孙本新
粉丝 1
博文 17
码字总数 4884
作品 0
海淀
程序员
垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收

垃圾回收器是一个级别很低的线程,它通过不定时监测程序使用的内存中被占用的动态分配的内存内的对象是否还存在它的引用来判断是否该回收那个内存单元,如果不存在则回收,否则相反~~并不是只要...

CYXLXD
2010/11/06
0
3
【译】.Net 垃圾回收机制原理(二)

上一篇文章介绍了.Net 垃圾回收的基本原理和垃圾回收执行Finalize方法的内部机制;这一篇我们看下弱引用对象,代,多线程垃圾回收,大对象处理以及和垃圾回收相关的性能计数器。 让我们从弱引...

长平狐
2012/06/08
57
0
关于垃圾回收的一些基本原理及技术解析

关于垃圾回收的一些基本原理及技术解析 什么是垃圾,为什么要垃圾回收?   垃圾回收是很大一块,在java虚拟机一些资料描述中,jvm大致干三件大事儿,1>加载class 2>分配存储空间 3>执行垃圾...

€5è¬þxãÍ
2017/08/13
0
0
java的gc(垃圾回收)

本文出自 “熔 岩” 博客,转载请与作者联系!:http://lavasoft.blog.51cto.com/62575/112126/ Java的垃圾回收总结 内存是稀缺的资源,哪怕内存一块钱一条!如果在编程中使用不当,再大的内存...

noteman
2016/08/25
44
0
Java中的对象和垃圾回收

1.java语言中的对象、数组等引用类型实体,系统都会为它在堆内存里面分配内存空间,当这个内存空间没有被引用时,java就会自动把它当做垃圾回收。垃圾回收机制有以下特点,垃圾回收机制只负责...

西红柿的眼泪
2016/07/09
7
0

没有更多内容

加载失败,请刷新页面

加载更多

linux 系统的运行级别

运行级别 运行级别 | 含义 0 关机 1 单用户模式,可以想象为windows 的安全模式,主要用于修复系统 2 不完全的命令模式,不含NFS服务 3 完全的命令行模式,就是标准的字符界面 4 系统保留 5 ...

Linux学习笔记
49分钟前
1
0
学习设计模式——命令模式

任何模式的出现,都是为了解决一些特定的场景的耦合问题,以达到对修改封闭,对扩展开放的效果。命令模式也不例外: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。 解决了这...

江左煤郎
56分钟前
2
0
字典树收集(非线程安全,后续做线程安全改进)

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀. 1、这个需求首先需要设计好数据结...

算法之名
昨天
10
0
GRASP设计模式

此文参考了这篇博客,建议读者阅读原文。 面向对象(Object-Oriented,OO)是当下软件开发的主流方法。在OO分析与设计中,我们首先从问题领域中抽象出领域模型,在领域模型中以适当的粒度归纳...

克虏伯
昨天
0
0
Coding and Paper Letter(四十)

资源整理。 1 Coding: 1.Tomislav Hengl撰写的非官方作者指南:Michael Gould•Wouter Gerritsma。 UnofficialGuide4Authors 2.R语言包rwrfhydro,社区贡献的工具箱,用于管理,分析和可视化...

胖胖雕
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部