垃圾回收
Java提倡的自动内存管理可以归结为两部分: 给对象分配内存 和 回收不再使用的内存,回收不再使用的内存就是垃圾回收。而垃圾回收又可以分为两个问题:什么是垃圾,怎么回收垃圾?
1)什么是垃圾?
不再使用的内存就是垃圾。
识别垃圾的经典算法有引用计数法(计数器)和可达性分析算法(对象引用链)。需要注意的是:不可达对象不会马上回收,至少要经过两次标记。
2)怎么回收垃圾?
首先,我们看看垃圾回收策略经典的三种算法(标记清除、复制、标记整理)和分代收集。
- 标记清除:先标记再清除,但是会有效率不高和空间碎片化问题。
- 复制算法:内存分为等大两块,一个用完了将剩余的复制到另一块。但是内存要降低一半.
- 标记整理算法:标记后不是清理对象,而是将存活对象移向内存的一端。
而分代收集里,根据不同生命周期将对象分为新生代和老生代,采用不同回收策略进行回收。
新生代采用复制算法,老生代采用标记清除和标记整理的算法。
3)垃圾回收器:
算法策略都是理论,我们还是要看实际上的应用,也就是垃圾回收器。所有的垃圾回收器的目的都是减少STW(也就是JVM要执行GC而对应用程序的停顿)。
垃圾收集器有Serial收集、Serial 0ld收集器、ParNew收集器、Parallel Scavenge收集器、parallel 0ld收集器,当然还有重要的CMS收集器和G1收集器。
CMS收集器
采用标记清除算法,但是要复杂一些,分为4个步骤:初始标记、并发标记、重新标记以及并发清除。
优点是并发收集和低停顿,缺点是CPU资源敏感、无法处理新垃圾。
G1收集器
G1抛弃了分代收集的方式,把内存划分为大小相等的独立区域。G1的优势就是停顿时间STW可预测,我们可以自己设置,这在CMS里是不可预估的。
在具体使用的时候,如果内存较小就CMS会占优,内存较大G1会更好。