- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java垃圾回收之标记清除算法详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
java垃圾回收算法之-引用计数器,这个算法其中一个优点便是,实时性,只要对象的引用计数器的值为0,则立刻回收。接下来介绍的标记清除算法,当对象的引用计数器的值为0时,不会立刻被回收的.
概念介绍 。
root对象 。
在标记清除算法中,会把如下对象称之为root对象 。
可访问的对象 。
如果栈中有一个变量a引用了一个对象,那么该对象是可访问的,如果该对象中的某一个字段引用了另一个对象b,那么b也是可访问的。可访问的对象也称之为live对象 。
标记清除算法介绍 。
该算法有两个阶段.
1. 标记阶段:找到所有可访问的对象,做个标记 2. 清除阶段:遍历堆,把未被标记的对象回收 。
备注:
标记阶段算法 。
伪代码类似如下:
1
2
3
|
for
each root variable r
mark (r);
sweep ();
|
为了能够区分对象是live的,可以为每个对象添加一个marked字段,该字段在对象创建的时候,默认值是false 。
假设有一个对象p,p对象还间接的引用了其他对象,那么可以使用一个递归算法去进行标记,例如:
1
2
3
4
5
|
void
mark(object p)
if
(!p.marked)
p.marked =
true
;
for
each object q referenced by p
mark (q);
|
这个mark方法只有当所有对象已经被mark后才会退出.
清除阶段算法 。
在这个阶段,需要去遍历堆中所有对象,并找出未被mark的对象,进行回收。与此同时,那些被mark过的对象的marked字段的值会被重新设置为false,以便下次的垃圾回收.
伪代码如下:
1
2
3
4
5
6
|
void
sweep ()
for
each object p in the heap
if
(p.marked)
p.marked =
false
else
heap.release (p);
|
下面用一张图来表示标记清除算法的整个过程.
标记清除算法的优点和缺点 。
1. 优点 - 是可以解决循环引用的问题 - 必要时才回收(内存不足时) 。
2. 缺点: - 回收时,应用需要挂起,也就是stop the world。 - 标记和清除的效率不高,尤其是要扫描的对象比较多的时候 - 会造成内存碎片(会导致明明有内存空间,但是由于不连续,申请稍微大一些的对象无法做到),如下图:
解决循环引用 。
出现循环引用的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class
testa{
public
testb b;
}
class
testb{
public
testa a;
}
public
class
main{
public
static
void
main(string[] args){
a a =
new
a();
b b =
new
b();
a.b=b;
b.a=a;
a =
null
;
b =
null
;
}
}
|
对应的图如下:
这个时候,当a = null; b = null;的时候,图像变成如下:
那么使用标记清除算法是可以回收a和b的,原因是标记清除算法是从栈中根对象开始的,改算法走完后,a对象和b对象是没有被标记的,会被直接回收.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持。如果你想了解更多相关内容请查看下面相关链接 。
原文链接:https://blog.csdn.net/linsongbin1/article/details/51577310 。
最后此篇关于Java垃圾回收之标记清除算法详解的文章就讲到这里了,如果你想了解更多关于Java垃圾回收之标记清除算法详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 C 新手,还没有真正掌握 C 何时决定释放对象以及何时决定保留对象。 heap_t 是指向结构堆的指针。 heap_t create_heap(){ heap_t h_t = (heap
我有一个问题,我不知道如何解决。问题是: char * ary = new Char[]; ifstream fle; fle.open(1.txt, ios_base::binary); fle.s
假设我在 C# 中有字符串:“我看不到你……” 我想删除(替换为空等)这些“’”符号。 我该怎么做? 最佳答案 那个“垃圾”看起来很像有人将 UTF-8 数据解释为 ISO 8859-1 或 Wi
我无法在解析方法中更改蜘蛛设置。但这绝对是一种方式。 例如: class SomeSpider(BaseSpider): name = 'mySpider' allowed_domains
在开始之前,我们先回顾一下堆是个什么玩意,大家可能都知道,我们每天创建的Java对象几乎都存放在堆上面,所以说堆是一个巨大的对象池一点都不过分,在这个对象池里面管理者数据巨大的对象实例。 在对
我想知道为什么 printf() 在提供数组且没有格式化选项时成功打印字符数组,但在使用整数数组时编译器会抛出警告并打印垃圾值。 这是我的代码: #include int main() { c
我正在研究 Scrapy 库并尝试制作一个小爬虫。 这是爬虫的规则: rules = ( Rule(LinkExtractor(restrict_xpaths='//div[@class="w
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Printing a string to a temporary stream object in C++
这个问题在这里已经有了答案: Are WebGL objects garbage collected? (2 个答案) 关闭 3 年前。 在 WebGL 中,纹理的创建和销毁使用: WebGLTex
我继承了以下代码: (为保护无辜者更改了一些名称。) package foo.bar.baz; import javax.swing.JPanel; //Main panel in the GUI c
如果我没记错的话,在某些情况下,Java 中的 lambda 会生成为匿名类实例。例如,在这段代码中,lambda 需要从外部捕获一个变量: final int local = 123456; lis
我正在阅读托管代码中的内存泄漏,想知道是否可以在 C# 不安全代码中创建它? unsafe { while(true) new int; } 我不确定如果它作为不安全代码运行,是否会被 GC
假设我有以下用 HTML 编写的网页(仅正文部分): ... function fn() { // do stu
我想知道是否有简单的命令可以删除在 latex 编译过程中生成的所有不必要的文件,例如.aux、.log 等 最好将它链接到常规的 Latex 构建命令,这样在我点击“编译”后,垃圾文件就会被删除。
Java 在 Java7 中引入了带有字符串的 switch case。我想知道使用这样的开关盒是否会产生垃圾。 例如在我的程序中, String s = getString(); switch(s)
Cevelop将 char junk 作为“未初始化的变量”对象。在这种情况下,解决问题的正确方法是什么? friend std::ostream& operator>(std::istream&
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and t
我正在编写一个发送和接收纯文本的小型 boost asio tcp 服务器和客户端。通信或多或少是请求响应。在测试期间,我想我只是向服务器发送垃圾数据,向它发送 100.000 个请求。 客户端发
我正在使用 SAX 来读取/解析 XML 文档,并且它工作正常,除了这个特定的站点,在该站点中 eclipse 告诉我“文档元素之后的垃圾”并且我没有返回任何数据 http://www.zachblu
这是我的 Scrapy 爬虫代码。我正在尝试从网站中提取元数据值。没有元数据在一个页面上出现多次。 class MySpider(BaseSpider): name = "courses"
我是一名优秀的程序员,十分优秀!