GC(垃圾分代收集)
GC(垃圾收集机制)
一、如何识别一个垃圾对象?
- 引用计数法
- GCRoot引用链
二、分代收集机制
一般垃圾回收发生在堆区,很少有在方法区发生,所以方法区被称为永久代
-
新生代
-
包括Eden、from survivor、to survivor三个区
-
在这个区采用的是复制收集算法,即:
- 先将Eden、from survivor中存活的对象复制到to survivor区中
- 清空Eden、from survivor两个区
- 最后将to survivor区中的对象复制到from survivor区中,并清空to survivor区
-
-
从新生代到老年代
- 大对象直接进入老年代
- 新生代survivor中年龄达到15的对象,移入老年代
- 为survivor区作担保,其内存已满而不能存储的对象存储在老年代中
-
老年代
-
老年代因为对象的存活率高(复制的代价就要高),也没有担保空间,所以采用标记清除/整理法
-
CMS收集:
- stop the world初步标记(初步标记GCROOT直接关联的对象)
- 并发标记(进行GCROOTS跟踪过程)
- stop the world重新标记(修正在2阶段产生的垃圾)
- 并发清除
优点:可以知道大量的标记和清除都在并发阶段执行,所以其垃圾收集停顿时间极短,可以提高用户的交互体验。
-
-
为什么要分代收集呢?
可以知道很多对象都是朝生夕死的,那么新生代就起到了一个缓存一样的作用,集中的处理新垃圾,而存活率高的对象则放在老年代,使垃圾收集的代价降低了
-
Minor GC和Full GC
新生代快满的时候就会触发Minor GC,Minor GC是比较频繁的GC,一般耗时较少
老年代快满了或者System.gc()建议,则会触发Full GC,Full GC会对整个堆进行GC,甚至包含几次Minor GC,所以耗时较长
-
永久代
主程序运行时似乎不会对永久代进行回收?
在jdk1.8中,为了防止方法区溢出,将方法区改为元数据区,将其放到的堆外内存(本地内存)中去了,那么他的大小就不受JVM的限制了。