JVM的垃圾收集算法以及应用
了解垃圾回收,需要知道垃圾回收的过程,以及处理方式,而回收过程是依赖于堆内存的回收规则以及堆的各部分处理方式,而这些方式是由垃圾收集算法决定的。常见的垃圾回收算法常见的有四种,分别是标记-清除算法,复制算法,标记-整理算法,分代收集算法。
标记-清除算法
概述:扫描并标记所有需要回收的对象,标记完成之后,再统一清理被标记的对象。
优点:是最基础的垃圾收集算法,往后的收集算法都是基于此进行优化以及改进。
缺点:一是效率,标记和清除过程效率都不高,二是空间问题,因为标记 清除过后,部分内存被释放,部分还会占用着,导致会出现内存空间出现大量不连续的内存碎片,导致下次分配大对象的时候,没有足够的内存进行分配。
复制算法
概述:把可用内存容量划分为大小相等的两块,每次就使用其中一块,用完这块后,把该块内存的对象复制到另外一块内存上去,再把之前那块的对象清理掉,这样就不会担心出现类似标记-清除算法中的内存碎片问题。
优点:一是效率相对标记-清除的升高了,二是不会出现大量内存碎片的问题。
缺点:牺牲了可用内存的一半来换取了效率,导致可用内存下降;二是增加了复制操作,效率有所降低。
应用:现在的商业虚拟机中,JVM的堆内存的年轻代都是采用了这种算法来进行回收。年轻代大部分对象都是短命的,所以大部分都会被回收掉,所以,并不需要按照1:1的方式进行划分内存。实际上,JVM的堆内存的年轻代是分为Eden区,from survival区和to survival区,三者的比例是8:1:1,垃圾回收的过程是 将Eden区和 from survival区 的对象移到 to survival区。这样的话,其实可用内存其实被浪费的只有10%。如果回收过程,转移到 to survival区的对象放不下,将会将对象转移到年老代(担保机制)。
标记-整理算法
概述:扫描并标记所有需要回收的对象,标记完成之后,让存活的对象向一端移动,然后将端边界以外的内存进行清理。
优点:没有复制,效率相对提升,同时又没有牺牲内存,有没有产生内存碎片。
应用:比较适合老年代对象的特点,因为存活对象比较多,也没有额外空间进行分配担保。
分代收集算法
概述:综合以上几种收集算法,将java堆分为年轻代和老年代,然后根据各代的特点采用对应的算法。年轻代,对象死去的早,只有少数存活,适合采用复制算法;年老代,对象存活率高,没有额外的空间进行分配担保。
应用:现代大多数虚拟机采用都是分代收集算法。