首先这个 GC 主要是针对堆内存的。
而 HotPot 虚拟机会把堆分为新生代 Eden
和老年代以及survivor
幸存区。
为什么需要
survivor
区,主要是因为如果没有这个区,只有新生代和老年代的话。
- 新生代每次内存快满的时候触发
Minor GC
时都直接把幸存的对象加入老年代,就可能导致老年代的内存很快就会满从而触发Full GC
,而FULL GC
的耗时是很长的, 会触发 STP 问题,不方便对老年代进行垃圾回收。- 有了幸存区,可以理解成一层缓冲,新生代对象在经历一次垃圾回收后,如果存活就先防、放在 survivor 区中,如果多次都存活,则再加入到老年代,对老年代管理对象比较友好。
触发 GC 的时机
对于新生代内存耗尽的情况,会触发
Minor GC
,对新生代进行垃圾回收,然后把存活对象加到survivor
区,多次存活则转移到老年代。对于老年代而言,是触发
FULL GC
(FULL GC 是对整个堆进行垃圾回收)。- 对于 Serial GC 串行垃圾回收器,会在老年代剩余内存小于”平均转入老年代的新生代所需内存大小“时,会触发
FULL GC
。 - 对于 CMS 等各种并发垃圾回收器,会每隔一段时间检查一下老年代内存空间占用是否超过一定比例,如果超过则进行
FULL GC
。
- 对于 Serial GC 串行垃圾回收器,会在老年代剩余内存小于”平均转入老年代的新生代所需内存大小“时,会触发
减少 FULL GC 的次数
其实从触发要求来看,可以找到如下解决方法:
- 增加新生代或老年代的内存大小,能装的对象多了,也就能够减少触发的机会。
- 一般老年代使用的垃圾回收算法是‘‘标记-整理’‘,就是把存活的对象移到内存的一侧,这样能够流出足够的空间存放其他对象,从而减少 GC。