jvm垃圾收集算法
垃圾收集算法
- 标记-清除算法:正如他的名字一样,标记-清除算法就是先把需要回收的对象打上标记,表明该对象需要回收了,然后再进行统一的垃圾回收。但是这种算法有两个缺点:1、效率问题,标记和清除的过程效率很低;2、空间问题,标记-清除算法会产生大量的内存随便,可能我们在进行较大内存分配的时候,因为没有合适的内存碎片使用不得不发动一次GC
- 复制算法:为了解决标记-清除算法的效率问题,一个新的算法思想产生了;我们把总的内存分为两块一样大小的内存,然后每次只使用其中的一块,一块用完了,就把或者对象复制到另外一块内存里面,然后清除这块的内存。这个算法确实大大提高了效率,由于回收区域和使用区域分离开了,也不用发生停顿了。但是这个算法有个很大的缺陷,我们宝贵的内存一次只能使用一半,代价太大了。困难总是需要聪明的人去解决的,IBM研究表明,我们的新生代里面,其实大约98%的对象都是”朝生夕死“的,所以每次回收时候,新生代中绝大部分的对象是需要回收的对象,根据这一研究,提出了节省内存的另外一个方案,我们把新生代分为eden和两个servivor区域,其中eden区域占整个新生代内存的80%,两个servivor区各占10%。对象刚被创建出来的时候放在eden区域,连个servicor区只使用一个,每次垃圾回收的时候,我们把eden区和servivor区的存活对象放在另外一个未使用的servivor区,然后对这两个区域进行清除。但这种方案,因为servivor区内存较小,当我们创建的对象太大或者存活对象过多的时候,又或者是发现某些对象多次回收依然坚挺没被回收到的时候,我们的虚拟机就会把该对象移动到老年代,算是对小小的servivor最后一次”托底“。
- 标记整理算法:我们的标记整理算法几乎完美的解决了我们的新生代的垃圾回收的各个问题,但是该算法是适用于对象回收比例很高的场景,试想一下,如果我们把这个复制算法使用到老年代会发生什么问题?老年代的回收率非常低下,我们不得不把大量的不需要回收的对象在servivor区来回复制,由于我们的存活对象非常多,甚至极限情况100%存活率,会发生什么,我们所有的对象都必须来回复制,这就需要我们浪费一半的内存来实现。所以我们就需要一个适用于我们老年代的垃圾回收算法。这时候,有人提出了标记—整理算法,老年代发生回收的时候,我们把标记不需要回收的放在内存的一边,需要回收的放在另外一边,然后对需要回收的区域进行回收操作。
- 分代收集算法:当前商业虚拟机的垃圾收集都采用“分代收集”(GenerationalCollection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。
jvm垃圾收集算法
原文地址:https://www.cnblogs.com/dazhaung/p/13345971.html