JAVA-JVM垃圾回收算法简介

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://xxlcube.blog.csdn.net/article/details/8216581

1、引用计数法

顾名思义,引用计数法就是对堆中的所有对象的引用进行计数,当这个计数为0时,表明该对象已经不被引用了,那么垃圾回收器则对其进行回收,每个对象都配备一个整型的计数器,负责记录该对象的引用次数,只要有任何一个对象引用了A对象,则A对象的计数器+1,当引用失效时,引用计数器-1,为0回收。

但是这种情况,不能回收循环引用的情况,比如A对象引用了B对象,B对象引用了A对象,且堆中没有其它任何对象,那么这时,其实A,B都应该回收的,没有任何意义,但是这种垃圾回收算法没办法回收。


2、标记-清除算法

分为标记阶段和清除阶段

·标记阶段

从根节点开始,标记所有根节点开始可达的对象节点,这个可达包括间接的,不是仅仅直接可达的,那么未标记的对象就是未被引用的对象,也就是垃圾对象

·清除阶段

清除所有未被标记的垃圾对象

这种算法的缺点是清除之后的可用内存是分散的,产生了很多零散的空间内存碎片,不利于再利用


3、复制算法

对象复制的思想,将原有的内存空间分为两块,每次只是用其中一块,当垃圾回收时,将正在使用的内存的存活对象复制到未使用的那个内存块,当然是连续存放的,这样原来那个内存块中就只剩下将要被回收的对象了,我们一次性全部清除即可,这样,原来的内存块就彻底干干净净了,而先用的内存块连续存放了存活的对象,以后继续交替使用。

这样效率高,但是内存开销大

JAVA的Young Generation中串行垃圾回收器中,使用了复制算法的思想,YG中分为Eden+S0+S1,S0=from,S1=to,from和to是两块大小相同,地位相同的空间,from和to也称为survivor空间,存放未被回收的对象

在垃圾回收时,Eden空间中存活的对象将复制到未使用survivor空间中的S0(也可以是S1),那么正在使用的是S1,S1中的年轻对象也会复制到S0中,大对象或者老年对象直接进入老年代Tenured,如果S0空间满了,则对象直接进入Tenured,此时,Eden空间和S1空间中剩余的对象就是垃圾对象,可以直接清空,S0存放的是此次回收后的存活对象。

YG比较适合使用复制算法,因为YG中垃圾对象通常多于存活对象


4、标记-压缩算法

适用于老年代,因为老年代大部分对象都是存活对象

类似标记-清除,从根节点开始扫描,可达对象标记,将标记的可达对象压缩到内存的一端,这样,内存又是连续了,然后从存活对象的内存地址的边界处清除所有的空间,这样,避免了碎片的产生,又不需要两块相同的内存块。


现在广泛使用的HotSpo虚拟机中YG使用的是复制算法,Tenured使用的是标记-压缩算法









展开阅读全文

没有更多推荐了,返回首页