JAVA基础——JVM之垃圾回收算法

JVM 的垃圾回收算法

​ 在 JVM 中,经常使用的垃圾回收算法有:标记-清除算法、标记-整理算法、复制算法以及分代回收算法,在这里会逐一介绍说明

标记-清除算法(Mark Sweep)

​ 标记清除算法的运行流程是先标记,将有引用链连接的引用对象进行标记,再将未被标记的引用对象的起始地址和结束地址存入空闲地址列表中,下次需要内存时直接对其进行覆盖

​ 标记清除算法从原理上来说很容易实现,但有一个很严重的问题是此算法容易产生内存碎片,因为标记清除算法回收后的内存可能是断断续续的,而此时就不再可能分配出较大的连续内存空间而触发新一次的垃圾回收

​ 标记清除算法在存活的引用对象多的时候十分高效,但因为其只对未被引用链所连接的即未被标记的引用对象进行清除操作,不移动被标记的对象,所以产生内存碎片是不能避免的

标记-整理算法(Mark Compact)

​ 标记整理算法的标记过程和标记清除算法没有区别,整理的过程会对使用的内存进行整理,将存活的对象都向内存的一端移动,然后清理掉整端边界以外的内存

​ 标记整理算法显然解决了标记清除算法会产生内存碎片的问题,但该算法中涉及到对象的移动,所以运算时的成本会有所提高

复制算法(Copy)

​ 复制算法是将内存区域分成了大小相等的 FROM 和 TO 两块区域,TO 区开始没有对象,所有的对象都使用 FROM 区,当 FROM 区满了需要垃圾回收时,将存活的对象复制到 TO 区中,然后把 FROM 区清空,这样一来复制到 FROM 区的对象是相连的,不会产生内存碎片的问题,最后改 FROM 为 TO,改 TO 为 FROM,这样新的对象就和老对象继续使用新的 FROM 区,而新的 TO 区依然是空的,如此循环

​ 复制算法实现起来十分简单,也不会产生内存碎片,但缺点是以内存空间的使用率为代价,每次只能使用一半的内存空间,如果存活对象多的话,复制算法的效率也会下降

分代回收算法(Generational Collention)

​ 首先分代收集是大部分 JVM 都采用的垃圾回收算法,它将内存划分为不同的区域,根据对象的生命周期对其进行分类,一般分为:新生代(Young Generation)和老年代(Tenured Generation)

​ 新生代中,又被分成一块伊甸园(Eden Space)和两块幸存区(Survivor),幸存区 FROM 和幸存区TO,其比例一般为 8 : 1 : 1,每次都同时使用伊甸园和幸存区 FROM,在进行垃圾回收时(Minor GC),将伊甸园和幸存区 FROM 中的对象复制进幸存区 TO 中,然后清理掉伊甸园和幸存区 FROM,最后像复制算法一样对 FROM 和 TO 进行一次调换如此循环,也就是说,新生代的垃圾回收主要以复制算法为主

​ 在分代回收算法中,有一个用来控制新生代对象进入老年代的属性,叫阈值,每次垃圾回收后,若该对象还存在于内存中,它的年龄就会 + 1,当对象的年龄超过阈值后,它就会从新生代晋升到老年代,也就是说,老年代存放的都是一些生命周期很长的对象

​ 当老年代内存全部被占用时,会先尝试 Minor GC,若空间仍不足,会再进行一次 Full GC,Full GC 的 STW(Stop The World)时间很长,如果 Full GC 后空间仍不足,就会 OOF

发布了38 篇原创文章 · 获赞 44 · 访问量 3418

猜你喜欢

转载自blog.csdn.net/scfor333/article/details/103703829