JVM垃圾回收(二)-垃圾收集算法
标记-清除算法
含义: 最基础的收集算法是“标记清除算法”,算法分为“标记”和清除两个阶段;首先标记出所有需要回收的对象,在标记完成后统一回收到所有被标记的对象。
主要问题:
- 效率问题,标记和清除两个工程效率都不高
- 空间问题,标记清楚后会产生大量不连续的内存空间,如图所示
复制算法
含义:将内存按容量划分为大小相等的两块,每次只使用其中的一块。当着一块的内存用完了,就讲还活着的对象复制到另外一块上面,然后在吧已使用过的内存空间一次性清理掉。这样使得每次都是对整个半区进行内存回收,内存分配是也不用考虑内存碎片等复制的情况。只要移动堆顶指针,按顺序分配内存既可。
- 优点:实现简单,运行高效
- 代价:讲内存缩小为原来的一半
复制算法的执行过程如图所示
新生代中的复制算法
先引入两个概念,在JVM堆内存中,又分为新生代和老年代
- 新生代:主要是用来存放新生的对象。一般占据堆的1/3空间。
- 老年代:主要存放应用程序中生命周期长的内存对象。
在Java虚拟机中一般都是采用这种收集算法来回收新生代。由于新生代中的对象98%是“朝生夕死”的,所以将内存分为较大的一块Eden空间和两块较小的Survive空间。
每次使用Eden和其中一块Survive。当回收时,将Eden和Survive中还存活着的对象一次性复制到另外一块Survive空间上,最后清理掉Eden和刚在用过的Survive空间。
在HotSpot虚拟机默认的比例是8:1(通过参数设置可以调整),也就是新生代可用内存空间为整个新生代容量的90%(80+10),由于无法保证每次回收都只有不多余10%的对象存活,当Survive空间不够用时,需要依赖其他内存进行分配(既老年代的内存)。
注:新生代的复制将内存分为三块,而不是两块。和其本身的特性有关,暂时先不讨论
标记-整理算法
标记的过程与“标记清除”一样,但后续步骤不是直接对可回收的对象进行清理,而是将所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。如图所示
分代收集算法
根据对象存活的周期的不同将内存划分为几块,在根据不同的特点,采取最适当的收集算法
- 新生代:存在大量的对象死亡,只有少数对象存活,采用复制算法
- 老年代:因为对象存活率高,则采用标记整理算法进行回收