-
标记清除算法
- 标记清除将垃圾回收分为两个阶段,分别为标记阶段和清除阶段,在标记阶段首先通过根节点,标记所有从根节点开始的对象,未标记的对象就是未被引用的垃圾对象,然后在清除阶段清除所有未被标记的对象;缺点就是会产生大量的空间碎片,因为回收后的空间是不连续的所以给大对象分配空间的时候可能会提前触发full gc
-
复制算法
- 将内存分为两块,每次只使用其中的一块,在垃圾回收时将正在使用的内存中存活的对象复制到未被使用的内存中,之后清除正在使用内存中的所有对象,交换两个内存的角色,完成垃圾回收
-
标记整理
- 复制算法的高效性体现在存活对象少、垃圾对象多的前提下。这种情况在新生代经常发生,但是在老年代更常见的情况是大部分的对象都是存活的对象,如果继续使用复制算法的话成本将非常高
- 标记整理算法是一种老年代的回收算法,它在标记清除的算法上做了一些优化。首先也需要从根节点开始对所有可达对象做一次标记,但是之后并不像标记清除算法一样简单的清理未标记的对象,而是将所有存活对象压缩到内存的一端。之后,清理边界之外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高
-
增量算法
- 增量算法的基本思想是,如果一次性将所有的垃圾进行处理,啥药造成系统长时间的停顿,那么就可以让垃圾收集线程和程序线程交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。使用这种方式,由于在垃圾回收过程中,间断性地还执行了程序代码,所以能减少系统的停顿时间,但是由于线程切换和上下文转换的消耗,会使得垃圾回收的成本上升,造成系统吞吐量的下降。
- Serial收集器
- Serial收集器是最古老的收集器,他的缺点是当Serial收集器想进行垃圾回收的时候,必须暂停用户的所有进程,即stop the world。到现在为止,它依然是虚拟机运行在client模式下的默认新生代收集器,与其他收集器相比,对于限定在单个CPU的运行环境来说,Serial收集器由于没有线程交替的开销,专做垃圾回收自然可以获得最高的单线程垃圾收集效率
- Serial Old是Serial的老年代版本,它同样是一个单线程收集器,使用’标记整理’算法。这个收集器的主要意义也是被Client模式下的虚拟机使用。在Server模式下,它主要还有两大用途:一个是在JDK1.5及以前的版本中与Parallel Scanvenge收集器搭配使用,另外一个就是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure的时候使用。
- 通过指定-UseSerialGC参数,使用Serial + Serial Old的串行收集器组合进行内存回收
- ParNew收集器
- ParNew收集器是Serial收集器新生代的多线程实现,注意在进行垃圾回收的时候依然会stop the world,只是相比较Serial收集器而言它会运行多条进程进行垃圾回收
- ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境都不能百分百的保证能超越Serial收集器。当然,随着可以使用的CPU的数量的增加,它对GC时系统资源的利用还是很有好处的。它默认开启的收集线程数与CPU的数量相同,在CPU非常多(譬如32个,现在CPU动辄4核加超线程,服务器超过32个逻辑CPU的情况越来越多了)的环境下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集器的线程数。
- -UseParNewGC:打开此开关后,使用ParNew + Serial Old的收集器组合进行内存回收,这样新生代使用并行收集器,老年代使用串行收集器
- Parallel Scavenge 收集器
- Parallel是采用复制算法的多线程新生代垃圾回收器,似乎和ParNew收集器有很多的相似的地方。但是Parallel Scanvenge收集器的一个特点是它所关注的目标是吞吐量。停顿时间越短就越适合需要与用户交互的程序,良好的相应速度能够提升用户的体验;而高吞吐量则可以最高效率的利用CPU时间,尽快地完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
- Parallel Old收集器是Parallel Scavenge收集器的老年代版本,采用多线程和’标记整理算法’。这个收集器是在jdk1.6中才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于比较尴尬的状态。原因是如果新生代Parallel Scavenge收集器,那么老年代除了Serial Old收集器外别无选择。由于单线程的老年代Serial Old收集器在服务端应用上的’拖累’,即使使用了Parallel Scavenge收集器也未必能在整体应用上获得吞吐量最大化的效果,又因为老年代收集中无法充分利用服务器多CPU的处理能力,在老年代很大而且硬件比较高级的环境中,这种组合的吞吐量甚至还不一定有ParNew加CMS的组合给力。知道Parallel Old收集器出现后,吞吐量优先收集器终于有了比较名副其实的应用祝贺,在注重吞吐量及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器
- -UseParallelGC:虚拟机运行在Server模式的默认值,打开此开关后,使用Parallel Scavenge + Serial Old的收集器组合进行内存回收。-UseParallelOldGC:打开此开关后,使用Parallel Scavenge + Parallel Old的收集器组合进行垃圾回收
- CMS收集器
- CMS收集器是一个比较重要的回收器,CMS是一种获取最短回收停顿为目标的回收器,这使得它很适合用于和用户交互的业务。从名字就可以看出,CMS收集器是基于标记清除算法实现的。它的收集过程分为四个步骤:
- 初始标记和重新标记还是会stop the world,但是在耗费时间更长的并发标记和并发清除两个阶段都可以和用户进程同时工作
- G1收集器
- G1收集器是一款面向服务端应用的垃圾收集器。HotSpot团队赋予它的使命是在未来替换掉jdk1.5中发布的CMS收集器。与其他GC收集器相比,G1具有以下特点:
- 并行与并发:G1能更充分的利用CPU,多核环境下的硬件来缩短stop the world的停顿时间。
- 分代收集:和其他收集器一样,分代概念在G1中依然存在,不过在G1不需要其他的垃圾回收器的配合就可以独自管理整个GC堆
- 空间整合:G1收集器有利于程序长时间运行,分配大对象时不会无法得到连续的空间而提前触发GC
- 可预测的非停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒
- CMS:采用标记清除算法
- 解决这个问题的办法就是可以让CMS在进行一定次数的Full GC(标记清除)的时候进行一次标记整理算法,CMS提供了以下参数来控制:
- -XX:UseCMSCompactAtFullCollection
- -XX:CMSFullGCBeforeCompaction=5
- 也就是CMS在进行5次Full GC(标记清除)之后进行一次标记整理算法,从而可以控制老年代的碎片在一定的数量以内,甚至可以配置CMS在每次Full GC的时候都进行内存整理
|