java 垃圾回收算法和垃圾收集器
java垃圾回收算法以及原理
在java中常见的垃圾回收算法有四种,分别是标记清除算法、复制算法、标记整理算法以及分代回收算法。标记清除算法(Mark-Sweep算法)
标记清除算法是最基础的垃圾回收算法,容易实现,而且思想也很简单。根据算法的名字我们就大致可以猜到这个算法分为两个阶段进行,一个是“标记”阶段,另一个就是“清除”阶段,“标记”阶段的任务就是要找出所有需要被回收的对象,清除阶段就是回收被标记的对象。
具体过程如图所示,
标记清除算法其实特别好理解,一阶段标记,二阶段清除被标记的对象,释放它们占用的内存资源。
优点:实现起来容易,效率比较高。
缺点:标记清除之后容易产生大量不连续的内存碎片,不连续的内存碎片浪费了,空间这可能会导致无法对大对象分配足够空间而提前触发新的一轮垃圾回收。
复制算法(Copying算法)
优点:实现简单,运行效率高,不容易产生内存碎片
缺点:为了解决产生内存碎片的问题,在内存使用方面付出了比较高的代价,使用这种方法,
会使原来的内存直接缩小了一半。如果是在存活对象过多的情况下,该方法的效率将会大大降低。
标记整理算法(Mark-Compact算法)
标记整理算法能够解决复制算法的缺陷,该算法在标记阶段和之前提到的标记清理算法一样,都是把垃圾对象标记出来,但是不同的是,在完成标记之后,该方法不是直接把对象清理掉,而是将存活的非标记对象都向同一方向移动,然后清理掉存活对象边界之外的无用内存。
分代收集算法(Generational Collection算法)
分代收集算法是目前大部分jvm的垃圾收集器采用的算法。它相比之前提到的三个算法更为复杂,该算法的核心思想就是分区,根据对象存活的生命周期划分为若干个不同的区域。一般情况下堆区会被分为老年代和新生代,老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收的时候会有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
目前来说,大多数垃圾收集器对于新生代都采取复制算法,因为新生代中每次垃圾回收大部分对象,需要复制的存活对象数量较少,但是在新生代中并不是按照1:1来划分空间的,一般是先将新生代分为一块较大的块eden空间和两块较小的survivor空间,每次使用eden空间和其中一块survivor空间,进行内存回收的时候,将eden和survivor中还存活的对象复制到另一块survivor空间中,然后清理掉eden和刚才使用过的survivor空间。
对于每次回收对象数量较少的老年代来说,一般使用标记整理算法
jvm中典型的垃圾收集器有哪些
**1.Serial/Serial Old收集器**年代最久远的收集器,它是单线程的,必须保证暂停了所有用户进程,才能进行垃圾收集。Serial收集器是针对于新生代的收集器,采用复制算法,Serial Old收集器是针对老年代的收集器,采用的是标记整理算法。该收集器实现起来比较简单,但是缺陷是必须暂停其它所有用户进程。2.ParNew收集器
Serial收集器的多线程版本,使用多个线程进行垃圾收集。
3.Parallel Scavenge收集器
新生代的多线程收集器,采用复制算法,和上述两种收集相比优点是不需要暂停其它用户进程。
4.Parallel Old收集器
是Parallel Scavenge收集器的老年代版本,因为针对老年代,所以使用标记整理法和多线程来处理垃圾对象。
5.CMS(Current Mark Sweep)收集器
一种并发的收集器,采用标记清除算法,是一种以获取最短回收停顿时间为目标的收集器
6.G1收集器
一款面向服务端应用的支持并发的收集器,能够充分利用多CPU、多核环境,并且能够建立可以预测的停顿时间模型。