Java-GC-标记压缩算法
标记压缩算法
其分为两个阶段标记阶段,和压缩阶段.其中标记阶段和标记清除算法的标记阶段是一样的.
- 对压缩算法来说,他的工作就是移动所有的可达对象到堆内存的同一区域中,使它们紧凑的排列在一起,从而将所有非可达对象释放出来的空闲内存集中在一起,以防出现标记清除算法的弊端.
在压缩阶段,由于要移动可达对象,那么就要考虑移动对象时候的顺序问题,一般分为一下三种:
- 任意顺序,不考虑原先对象的排列顺序,也不考虑对象之间的引用关系,随意移动可达对象,这样可能会有内存访问的局部性问题.
- 线性顺序,在重新排列对象时,会考虑到对象之间的引用关系,例如对象A引用了对象V,那么就会尽量将对象A,B排列在一起.
- 滑动排序,按照原先的排列顺序滑动到堆的另一端.
现在大部分垃圾回收算法都是按照任意顺序或者是滑动顺序去实现的.
Two-Finger算法
其实质是任意顺序移动,其最适合处理包含固定大小对象的内存区域.
该算法需要遍历堆内存两次,第一次是将堆尾的可达对象移动到堆开始的空闲内存单元(所以在前面说,最适合固定对象长度).第二次遍历则需要修改可达对象的引用,因为一些可达对象已经被移动到别的地址,而原先引用它们的对象还指向之前的地址.在这两次的遍历过程中,首位两个指针分别从对的头尾两个位置向中间移动,直至两个指针相遇.
LISP2算法
lisp2算法是一种应用更加广泛的压缩算法,它属于滑动顺序算法的一种.他和二指算法的不同之处在于它还可以处理大小不同的对象,而不是固定大小的对象(因此适用范围更加广泛).同时,计算出来的可达对象的迁移地址需要额外的空间进行存储而不是复写原先对象所在的位置.最后Lisps2需要三次堆内存的遍历.
第一次遍历
collector仅仅计算和记录可达对象应该迁移过去的地址.
compact():
computeLocations(HeapStart,HeapEnd,HeapStart)
updateReferences(HeapStart,HeapEnd)
relocate(HeapStart,HeapEnd)
computeLocations(start,end,toRegion):
scan <- start
free <- toRegion
while scan < end
if isMarked(scan)
forwardingAddress(scan) <- free
free <- free + size(scan)
scan <- scan + size(scan)

指针free和scan同时指向起始堆位置,同时scan开始向堆尾移动,目的是要找到被标记的可达对象.
发现可达对象之后,scan指针对应的位置分配一个额外的空间来存储该可达对象应该迁移到的地址,就是free指针指向的位置0,同时free指针向堆尾移动B对象大小的距离,free指针指向的位置.最后指针继续向前走,直到寻找到下一个可达对象D scan指针指向的位置.
同理,在可达对象D处分配一块空间来保存对象D应该迁移到的位置,由于B对象已经占用了2个内存单元,所以对象E的迁移地址是从位置2开始,也就是当前free指针指向的位置。
指针free,scan继续向前移动。
第一次遍历完后,所有的可达对象都有了对应的迁移地址,free指针指向位置9,因为所有的可达对象总共占了9个单元大小的空间。
第二次遍历
第二次遍历主要是修改对象之间的引用关系,基本和二指算法的第二次遍历一样.
updateReferences(start,end):
for each fld in Roots
ref <- *fld
if ref != null
*fld <- forwardingAddress(ref)
scan <- start
while scan < end
if isMarked(scan)
for each fld in Pointers(scan)
if *fld != null
*fld <- forwardingAddress(*fld)
scan <- scan + size(scan)

修改根对象的引用关系,根对象1引用对象B,对象B的迁移地址为0,于是collector将根对象对B对象的引用指向它的迁移地址 - 位置0, 现在A对象所处的位置。
同理,对于根对象2,3都执行同样的操作,将它们对其所引用的对象的引用修改为对应的它们所引用的对象的迁移地址。
通过scan指针遍历堆内存,更新所有的可达对象对其引用对象的引用为其引用对象的迁移地址。比如说,对于可达对象B,它引用了对象D,D的迁移地址是2,那么B直接将其对D对象的引用重新指向2这个位置。
第二次遍历结束后的对象之间的引用关系。
第三次遍历
第三次遍历则是根据可达对象的迁移地址去移动可达对象,比如说可达对象B,它的迁移地址是0,那么就将其移动到位置0,同时去除可达对象的标记,以便下次垃圾收集。
relocate(start,end):
scan <- start
while scan < end
if isMarked(scan)
dest <- forwardingAddress(scan)
move(scan,dest) //将可达对象从scan位置移动到dest位置
unsetMarked(dest)
scan <- scan + size(scan)

Java-GC-标记压缩算法的更多相关文章
- 《垃圾回收的算法与实现》——GC标记-压缩算法
基本算法 Mark-Compact与Mark-Sweep的第一阶段均为标记活跃对象,第二阶段则不同,压缩算法则是将活跃对象逻辑上移到一起. Lisp2算法 对象头中增加forwarding指针,其用法 ...
- Java GC 标记/清除算法
1) 标记/清除算法是怎么来的? 我们在程序运行期间如果想进行垃圾回收,就必须让GC线程与程序当中的线程互相配合,才能在不影响程序运行的前提下,顺利的将垃圾进行回收. 为了达到这个目的,标记/清除算法 ...
- JAVA GC之标记 第五节
JAVA GC之标记 第五节 OK,我们继续昨天最后留下的问题,什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方 ...
- jvm系列(三):java GC算法 垃圾收集器
GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...
- Java GC算法 垃圾收集器
GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为"GC",它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. ...
- [面试] Java GC (未整理完)
Java GC简介 什么是 GC ? Java程序不用像C++程序在程序中自行处理内存的回收释放.这是因为Java在JVM虚拟机上增加了垃圾回收(GC)机制,用以在合适的时间触发垃圾回收. 你都了解哪 ...
- jvm系列三、java GC算法 垃圾收集器
原文链接:http://www.cnblogs.com/ityouknow/p/5614961.html 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 ...
- Java虚拟机(二):Java GC算法 垃圾收集器
概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计数器.虚拟机栈.本地方 ...
- Java GC机制详解
垃圾收集 Garbage Collection 通常被称为“GC”,本文详细讲述Java垃圾回收机制. 导读: 1.什么是GC 2.GC常用算法 3.垃圾收集器 4.finalize()方法详解 5. ...
- Java GC垃圾回收
Java的内存分配和回收也主要在Java的堆上进行的,Java的堆中存储了大量的对象实例,所以Java的堆也叫GC堆. Java在垃圾收集的过程中,主要用到了分代收集算法,具体有复制.标记清除.标记压 ...
随机推荐
- sudo执行提示Command not found
运行一命令在普通用户下可行,切换到root用户依然可行,但在普通用户下使用sudo执行时,提示Command not found. 修改/etc/sudoers文件,找到类似下面的一行: Defaul ...
- UVA12103 —— Leonardo's Notebook —— 置换分解
题目链接:https://vjudge.net/problem/UVA-12103 题意: 给出大写字母“ABCD……Z”的一个置换B,问是否存在一个置换A,使得A^2 = B. 题解: 对于置换,有 ...
- python根据圆的参数方程求圆上任意一点的坐标
from math import cos, sin,pi x0,y0=0,0 r=4.0 angle=-25 x1 = x0 + r * cos(angle * pi / 180) y1 = y0 + ...
- html5--2.7新的布局元素(4)-time
html5--2.7新的布局元素(4)-time 学习要点 了解微格式的概念 掌握time元素的用法 微格式的概念 HTML5中的微格式,是一种利用HTML5中的新标签对网页添加附加信息的方法,附加信 ...
- struts2框架xml验证
struts2验证分为3步: 1.获取需要验证的信息,使用同名属性,提供getter,setter方法.然后框架使用反射将值自动注入. 2.对信息进行验证,成功失败作出对应的选择. xml验证和手动验 ...
- array_2.array_rand
从数组中随机取出一个或多个单元 <?php $arr = [1, 2, 3]; $rand = array_rand($arr, 2); var_dump($rand);
- hdu-5778 abs(暴力枚举)
题目链接: abs Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Pro ...
- 集训Day4
在bzoj刷了好几天杂题感觉手感不是很好 继续回来集训一下 好几天没更新了啊... bzoj1875 一个无向图,一个人要从起始点走$t$步走到终点,不能沿着刚走过来那条边回去,问有多少种走法 $m ...
- ACM学习历程—HDU1717 小数化分数2(gcd)
Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢? 请你写一个程序不但可以将普通小数 ...
- Linux系统上php-cli安装redis扩展
下载 假设已经安装了redis-server,现在我们来安装redis扩展. 下载ZIP包: https://github.com/phpredis/phpredis/tree/master . 解压 ...