GC发生在JVM哪部分,有几种GC,他们的算法是什么?
脑图:
GC发生在JVM哪部分
GC 发生在JVM的堆里面
JVM体系结构概况
有几种GC?
两种GC
- 年轻代 Minor GC
- 老年代 Full GC
- 基本不动Perm区无GC
GC的算法是什么
4种算法
1、引用计数法(java废弃)
给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;
计数器值为0的对象就是不再被使用的,垃圾收集器将回收该对象,若频繁被使用就将对象放到老年代中。
特点:速度快。但是"互相引用,循环引用"的对象却无法回收。(正是由于这个缺陷,这个算法不再被使用)
2、复制(Copying)算法
它将可用的内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉。
这样每次只对半个区域进行内存回收,内存分配时也不需要考虑内存碎片等复杂情况,只需要移动指针,按照顺序分配即可。
缺点:整体可用内存缩小了一半,这样代价太高了
现在的商用虚拟机都采用这种算法来回收新生代,新生代的内存被划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。
每次回收时,将Eden和Survivor中还存活着的对象一次性复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。当Survivor空间不够用时,需要依赖老年代进行分配担保(Handle Promotion)。
特点:
- 年轻代
- 效率高,没有内存碎片,占用空间大
复制算法的执行过程如图:
3、标记-清除(Mark-Sweep)算法
分为“标记”和“清除”两个阶段:首先标记出所有需要清除的对象,标记完成后统一清除所有被标记的对象。 不足主要体现在效率和空间: 从效率的角度讲,标记和清除两个过程的效率都不高; 从空间的角度讲,标记清除后会产生大量不连续的内存碎片, 内存碎片太多可能会导致以后程序运行过程中在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发一次垃圾收集动作。
特点:
- 效率低,有碎片
- 老年代
标记-清除算法执行过程如图:
4、标记-整理(Mark-Compact)算法
复制算法在对象存活率较高的场景下要进行大量的复制操作,效率很低。万一对象100%存活,那么需要有额外的空间进行分配担保。老年代都是不易被回收的对象,对象存活率高,因此一般不能直接选用复制算法。老年代的标记-整理算法,过程与标记-清除算法一样,不过不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。
特点:
- 老年代
- 需要移动碎片,效率低,没内存碎片
标记-整理算法的工作过程如图:
5、分代收集算法
现代商用虚拟机基本都采用分代收集算法来进行垃圾回收。这种算法就是上面内容的结合罢了,
根据对象的不同生命周期,将内存划分为几块,然后根据各块的特点采用最适当的收集算法。
大批对象死去、少量对象存活的(新生代),使用复制算法,复制成本低;
对象存活率高、没有额外空间进行分配担保的(老年代),采用标记-清理算法或者标记-整理算法。