垃圾回收机制

一关于引用的算法

1 什么是引用

在JDK1.2之后,java对引用的概念进行了扩充,将引用根据引用强度分为了4种引用,分别是:强引用、软引用、弱引用、虚引用。在这里分析垃圾回收关于引用的算法时,我们先抛开这些具体的分类,只是从引用的概念模型上进行分析。这里的引用就简单的指如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。接下来我们看一下引用计数与可达性分析算法。

2 引用计数法与可达性分析算法

引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。而这种算法有一个很大的缺点就是不能解决对象之间的循环引用的问题。
可达性分析算法就是根据一条以“GC Roots”对象为根节点的引用链来判断哪些对象是可进行垃圾回收的。java中的“GC Roots”对象包括:
1.虚拟机栈(栈桢中的本地变量表)中的引用的对象
2.方法区中的类静态属性引用的对象
3.方法区中的常量引用的对象
4.本地方法栈中JNI的引用的对象
下面的图中就解释了什么是可达性算法,以及引用计数算法的弊端。

这里写图片描述

这里写图片描述

如上图,一开始中间的对象上的引用计数为2,当根节点对象断开对该节点的引用时,它的引用计数变为了1,根据可达性分析算法,右边三个对象已经是可是被垃圾回收器回收的,但是要是按照引用计数法的规则来看,因为中间对象的引用计数并不为0,因此并不能被回收。因为这个主要原因,主流的java虚拟机并没有使用引用计数法来管理内存。

二 标记清除算法

标记-清除算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。
这里写图片描述

但这种算法从效率和空间上都有缺陷。标记和清除的效率不高,而且标记清除完后,会产生大量的空间碎片,这里碎片不连续,当下次程序运行分配较大的对象而找不到足够的连续空间的时候,不得不再进行一次垃圾回收。

三 分代收集算法

在介绍其他的收集算法之前,先将一下分代收集算法的概念。顾名思义,分代收集算法就是将内存中的区域根据对象的存活周期不同而将内存划分为不同的代区。一般是把java堆中分为新生代和老年代。针对对象生存周期或者大小将它们放入不同的代区,并采用针对性的收集算法。下面就讲一下针对新生代和老年代所使用的算法。

三 标记压缩算法

老年代一般存放的都是经过多次垃圾收集都没有被收集的对象,还有就是存放一些占用内存比较大的对象。这个区域也是新生代的一个担保区域。当一新生代中的 form - to 区没有足够的区域存放上次垃圾回收之后存活下来的部分对象时,老年代会充当一个担保区域来存放这个对象。当老年代没有足够的空间进行担保的时候,就要进行标记清除或者是标记压缩算法。
标记压缩算法算是对标记清除算法的一种优化。和标记-清除算法一样,标记-压缩算法也首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。

这里写图片描述

四 复制算法

新生代主要为为两个区域。Eden区 和 Survivor区。Survivor又是由两块大小相同的 from 区 和 to区组成。所有的对象刚一产生,就会进入Eden区(伊甸园,老外也会使用比喻的修辞手法)。再根据对象的特性决定它的去处。
复制算法是操控新生区中的Survivor区( from 区 和 to区),每次只使用其中一块,在垃圾回收时,将正在使用的内存(from 区)中的存活对象复制到未使用的内存(to区)块中,之后,清除正在使用的内存(from 区)块中的所有对象,交换两个内存的角色(from 区变为to区,to区变为程序正在使用的from区),完成垃圾回收。但这种算法的缺点恨明显,就是对内存空间的浪费,因为总有一块区域是被清空且参与不到程序运行当中去的。所以一般 Survivor区会分配的很小。HotSpot虚拟机默认Eden区 和 Survivor区的大小比例为8:1。因为每次进行垃圾回收后,Eden区和 Survivor区中的from区会被清除掉,按照这种比例,每次垃圾回收不超过只有10%的对象存活,我们不能保证这是绝对的,所以需要老年代作为担保区域。下面是对堆内存中垃圾回收的分析图:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值