找到了 "垃圾" 对象,如何标记 "垃圾" 对象?
标记-清除算法
先标记所有需要回收的对象,标记完成后统一回收被标记了的对象。(最基础的算法,其它算法在这个算法基础上改进的)
缺点:标记和清除的效率不高,标记和清除后会产生大量的内存碎片(空间问题)
复制算法
将内存按容量划分两块大小相等的内存块,每次只使用一块,当这一块使用完了,就将存活的对象复制到另外一块内存上,然后回收已使用过的那块内存,一次性清空内存空间。
特点:简单高效
缺点:内存缩小为原来的一半
现代的商用虚拟机都使用复制算法来回收新生代。因为新生代的对象98%左右都是"朝生夕死"的,所以可以不用按照1:1划分内存,而是将内存划分成一块大的Eden空间和两个小的Survivor空间。每次使用Eden和其中一块Survivor区域(From),当回收的时候,将Eden区和From区的存活对象复制到另外一块Survivor(To),然后清理掉Eden区和From区的空间。如果回收后,To区域的空间不够,则需要其他内存区域(老年代)进行分配拟担保。Eden区和Survivor区的划分比例默认是 8:1。
标记-整理算法
复制算法缺点是在对象存活率较高的情况下,需要复制更对的对象,效率将会变低,而且浪费空间,所以对于老年代,不使用这种算法。标记-整理算法是先对所有的对象进行标记,最后所有存活的对象都移向一端,然后清除端边界以外的空间。
分代收集算法
当前的商用虚机机都采用 "分代收集" 算法,根据不同代采用不同的标记算法,根据对象的生存周期将堆内存分为不同的几块,java堆中一般分为新生代和老年代,新生代使用的复制算法,老年代使用 "标记-清除" 或者 "标记-整理" 算法。
参考:《深入理解Java虚拟机:JVM高级特性与实践》
2018-07-25 17:15:28