因为垃圾收集算法的实现涉及大量的程序细节,并且每一个平台的虚拟机操做内存的方法又各不相同,所以博客中不过多的讨论算法的实现,只是介绍几种算法的思想以及发展。算法
标记清除算法分为“标记”和“清除”两个阶段,首先先标记出那些对象须要被回收,在标记完成后会对这些被标记了的对象进行回收;以下图:jvm
这种算法的优势在于不须要对对象进行移动操做,仅对不存活的对象进行操做,因此在对象存活率较高的状况下效率很是高,可是从上图模拟的结果来看对象被回收后,可用的内存并非连续的,而是断断续续,形成大量的内存碎片。 存储对象时要求内存空间时连续的,因此虚拟机在给新的内存较大的对象分配空间时,有可能找不到足够大的连续的空闲的空间来存放,从而引起一次垃圾回收动做,实际上里面是有大量的空闲空间的,只是不连续而已。spa
复制算法是将内存分为两块大小同样的区域,每次是使用其中的一块。当这块内存块用完了,就将这块内存中还存活的对象复制到另外一块内存中,而后清空这块内存。这种算法在对象存活率较低的场景下效率很高,好比说新生代,只对整块内存区域的一半进行垃圾回收,在垃圾回收的过程也不会出现内存碎片的状况,不须要移动对象,只须要移动指针便可,实现简单,因此运行效率很高。运行效率是在创建在浪费空间的基础上的,这是典型的已空间换时间的方法,由于每次只能是使用北村的一半。算法示意图以下:指针
如今商用的jvm中都采用了这种算法来回收新生代,由于新生代的对象基本上都是朝生夕死的,存活下来的对象约占10%左右,因此须要复制的对象比较少,采用这种算法效率比较高。hotspot版本的虚拟机将堆(heap)内存分为了新生代和老年代,其中新生代又分为内存较大的Eden区和两个较小的survivor区。当进行内存回收时,将eden区和survivor区的还存活的对象一次性地复制到另外一个survivor空间上,最后将eden区和刚才使用过的survivor空间清理掉。hotspot虚拟机默认eden和survivor空间的大小比例为8:1,也就是每次新生代中可用内存空间为整个新生代空间的90%(80%+10%),只会浪费掉10%的空间。固然,98%的对象可回收只是通常场景下的数据,咱们没有办法保证每次回收都只有很少于10%的对象存活,当survivor空间不够用时,须要依赖于其余内存(这里指的是老年代)进行分配的担保。对象
复制算法在对象存活率较高的状况下就要进行较多的对象复制操做,效率将会变低。更关键的是,若是你不须要浪费50%的空间,就须要有额外的空间进行分配担保,用以应对被使用的内存中全部对象都100%存活的极端状况,因此在老年代通常不能直接选用这种办法。blog
根据老年代的特色,有人提出了标记-整理的算法,标记过程仍然与标记-清楚算法同样,但后续步骤不是直接将可回收对象清理掉,而是让全部存活的对象都向一端移动,而后直接清理掉端边界之外的内存,算法示意图以下:生命周期
分代收集算法将heap区域划分为新生代和老年代,新生代的空间比老年代的空间要小。新生代又分为了Eden和两个survivor空间,它们的比例为8:1:1。对象被建立时,内存的分配是在新生代的Eden区发生的,大对象直接在老年代分配内存,IBM的研究代表,Eden区98%的对象都是很快消亡的。内存
为了提升gc效率,分代收集算法中新生代和老年代的gc是分开的,新生代发生的gc动做叫作minor gc 或 young gc,老年代发生的叫作major gc 或 full gc。博客
minor gc 的触发条件:当建立新对象时Eden区剩余空间小于对象的内存大小时发生minor gc;虚拟机
major gc 触发条件:
一、显式调用System.gc()方法;
二、老年代空间不足;
三、方法区空间不足;
四、重新生代进入老年代的空间大于老年代空闲空间;
Eden区对象的特色是生命周期短,存活率低,所以Eden区使用了复制算法来回收对象,上面也提到复制算法的特色是在存活率较低的状况下效率会高不少,由于须要复制的对象少。与通常的复制算法不一样的是,通常的复制算法每次只能使用一半的空间,另外一半则浪费掉了,Eden区的回收算法也叫作"中止-复制"算法,当Eden区空间已满时,触发Minor GC,清理掉无用的对象,而后将存活的对象复制到survivor1区(此时survivor0有存活对象,survivor1为空的),清理完成后survivor0为空白空间,survivor1有存活对象,而后将survivor0和survivor1空间的角色对象,下次触发Minor gc时重复上述过程。若是survivor1区剩余空间小于复制对象所需空间时,将对象分配到老年代中。每发生一次Minor gc时,存活下来的对象的年龄则会加1,达到必定的年龄后(默认为15)该对象就会进入到老年代中。
老年代的对象基本是通过屡次Minor gc后存活下来的,所以他们都是比较稳定的,存活率高,若是仍是用复制算法显然是行不通的。因此老年代使用“标记-整理”算法来回收对象的,从而提升老年代回收效率。
总的来讲,分代收集算法并非一种具体的算法,而是根据每一个年龄代的特色,多种算法结合使用来提升垃圾回收效率。