本文默认JVM为HotSpot,在介绍各款垃圾收集器以前先介绍下垃圾收集器的算法,不是讲解算法如何实现,而是介绍下算法的处理思想和一些优缺点。算法
垃圾收集器用于清除垃圾的算法有:标记-清除算法、复制算法、标记-整理算法。 用于针对对象不一样的存活周期而分代的算法有:分代收集算法。这个算法把Java堆分为新生代和老年代。cdn
标记-清除算法应该是最符合咱们人一开始处理垃圾的思路的算法,例如咱们想清除房间的垃圾,咱们确定是先定位(对应标记)哪些是垃圾,而后把这些垃圾以后扔了(对应清除),简单粗暴,剩下的不是垃圾的东西我也懒得理,无论了哈哈哈。对象
固然有的人说我打扫房间会先整理不是垃圾的东西而后把垃圾扔了...你走错片场了请去标记-整理片场(勤劳的孩子)。 blog
复制算法等于说根据标记-清除算法的不足之处进行了改进。简单的来讲它把空间切成了两半,一次我就用一半,一半满了我就把活着的对象放在另外一半按顺序放,而后无脑的把刚才使用的那一半空间一次清理干净,而后保留着存活的那些对象的内存空间换上去使用。这样就没了标记-清除算法的空间碎片问题。 内存
由于正常状况下新生代的大部分对象都是短命鬼,因此能活下来的很少,因此默认的空间划分比例是8:1:1。用法就是每次只使用Eden和一块Survivor,而后把活下来的对象都扔到另外一块Survivor。再清理Eden和以前的那块Survivor。而后再把Eden和存放存活对象的那一块Survivor用来迎接新的对象。就等于每次回收了以后都会对调一下两个Survivor。虚拟机
可是事情总有意外,万一这波对象短命鬼较少,存活下来的不少,那一个Survivor放不下,因此还有个担保机制,就像咱们现实生活中的担保人,你还不起了担保人上!这个担保人就是老年代,也就是Survivor放不下了就放老年代去。 那为何虚拟机基本上用这种算法来回收新生代呢?就是由于新生代的对象大部分存活时间不长,因此每次GC的时候复制的比较少,效率高啊,每次就复制一点点对象到Survivor。it
那要是到老年代也就是一些老不死的对象那用复制效率就低了啊,首先8:1:1这种分法就不合适了,由于每次存活下来的对象会不少,1就放不下了,你可能就得"五五开"分了,那"五五开"之分也就算了,由于每次对象基本上都活着,因此每次复制等于复制一半空间的对象。效率低啊。io
还有,新生代有老年代作担保啊,多了的对象能够放到老年代,而老年代不行啊,没有依靠了。因此就又有了下面的算法。class
标记-整理算法的思路也是和标记-清除算法同样,先标记那些须要清除的对象,可是后续步骤不同,它是整理,对就是像上面说的那些清除房间垃圾每次都会整理的人同样那么勤劳。 效率
这算法就是把Java堆分为新生代和老年代,这样好根据每一个代的对象存活时间特色上不一样的收集算法。 因此通常新老代就是用复制算法。老年代用标记-清除或标记-整理算法。
若有错误欢迎指正! 我的公众号:yes的练级攻略