作者:北京圣才 | 来源:互联网 | 2020-09-17 18:21
堆又叫做“GC堆",由于现在收集器基本都采用分代收集算法,所以Java堆还可以细分为:新生代和老年代,比例是1:2;再细致一点新生代内部又划分为Eden区、Survivor区。
这篇文章我们主要关注这些问题::Java程序执行完后,堆中的对象什么时候被回收?如何回收?堆又叫做 “GC堆,"由于现在收集器基本都采用分代收集算法,所以Java堆还可以细分为:新生代和老年代,比例是1:2;再细致一点新生代内部又划分为Eden区、Survivor区,比例为8:1。下图显示了堆的结构:
上面提到了引用,对象的存活都和引用有关,引用类型又分为强引用,软引用,弱引用,虚引用。
实际上可达性分析法判定的不可达对象不会马上回收,对象真正被回收需要经过两次标记。第一次标记就是被判定为不可达对象,然后进行一次筛选,筛选条件是此对象是否有必要执行finalize()方法。如果没有重写finalize()方法或者finalize()方法已经被虚拟机调用过,finalize()方法只会被系统调用一次。这两种情况都是”没有必要执行的“。如果有必要,这个对象会被放在F-Quene队列中,由虚拟机自动建立的低优先级的Finalizer线程去执行finalize()方法。这期间GC会对F-Quene中的对象进行第二次小规模标记,如果对象依然没有被引用,那就会被回收,没有被筛选的对象不一定被回收。
我们已经知道对象什么时候被回收了,那如何回收呢?介绍四种最常用的垃圾回收算法:
标记-清除:先标记需清除的对象,统一回收----效率不高,会产生大量不连续的碎片;
复制算法:将内存分块,每次只使用一块,使用完后,将存活的对象复制到另一块上;
标记整理:先标记存活对象,然后让所有存活对象向一端移动,直接清理端边界以外的内存;
分代算法,堆分队新生代和老年代,新生代每次收集都会有大量的对象死去,选择复制算法。老年代存活率比较高,且没有额外空间进行分配担保,选择标记清除或者标记整理算法。
垃圾收集算法是一种内存回收的思想,具体的实现是垃圾收集器。简要介绍下常用的垃圾收集器:
serial串行收集器。单线程,垃圾回收的时候,必须暂停其他工作。新生复制,老年标记整理。简单高效;
ParNew 收集器。serial的多线程版本;
Parallel Scavenge 收集器,复制算法的多线程收集器。注重吞吐量,cpu运行代码时间/cpu耗时总时间。新生复制,老年标记整理;
Serial Old 收集器,老年代版本;
Parallel Old 收集器,Parallel Scavenge老年代版本;
CMS 收集器,注重最短时间停顿。并发收集器,垃圾收集线程与用户线程(基本上)同时工作。 标记清除算法
关于垃圾收集器更多的细节可以阅读周志朋老师的书。
推荐教程:《JS教程》
以上就是浅析堆与垃圾回收机制的详细内容,更多请关注 第一PHP社区 其它相关文章!