垃圾收集算法
标记清除算法
对无效对象进行标记,然后清除。复制算法
将内存空间分为两块,每次只使用一块。当一块的内存满了之后,将存活的对象移动到另一块区域。标记整理算法
对无效对象进行标记,然后将存活的对象移动到堆的一端,清除存活对象之外的空间。分代收集算法
根据对象存活的不同生命周期,将堆内存划分为老年代和新生代。老年代每次GC只有少量垃圾被回收,新生代每次GC会有大量的垃圾被回收,因此可以根据不同的区域选择不同的算法。分区收集算法
将整个堆空间划分为连续的不同区间,每个小区间独立使用,独立回收。这样做的好处是可以控制一次回收多少个区间,根据目标停顿时间,每次合理的回收若干个小区间(而不是整个堆),从而减少一次GC产生的停顿时间
垃圾收集算法的优缺点
垃圾收集器
Serial垃圾收集器(单线程,复制算法)
使用Serrial收集器,无论进行Minor gc还是Full GC清理对空间时,所有线程都会被暂停。ParNew 垃圾收集器(Serial+多线程)
Serial的多线程版本,GC时所有线程也会被暂停。
ParNew 收集器默认开启和 CPU 数目相同的线程数,可以通过
-XX:ParallelGCThreads 参数来限制垃圾收集器的线程数。
ParNew虽然是除了多线程外和Serial 收集器几乎完全一样,但是ParNew垃圾收集器是很多 java虚拟机运行在 Server 模式下新生代的默认垃圾收集器。Parallel Scavenge 收集器(多线程复制算法、高效)
和ParNew非常相似,但它的目标是达到一个可控的吞吐量。
吞吐量 = 运行用户代码时间/(运行用户代码时间+垃圾回收时间)。
高吞吐量可以最高效的利用CPU时间,尽快的完成程序运算任务,主要适用于在后台运算而不需要太多交互的任务。Serial Old 收集器(单线程,标记整理算法 )
Serial收集器的老年代版本。Parallel Old 收集器(多线程标记整理算法)
Parallel Old 收集器是Parallel Scavenge的年老代版本。Parallel Old 正是为了在年老代同样提供吞吐量优先的垃圾收集器,如果系统对吞吐量要求比较高,可以优先考虑新生代 Parallel Scavenge和年老代 Parallel Old 收集器的搭配策略。CMS 收集器(多线程标记清除算法)
它的目标是获取最短的垃圾回收停顿时间。
CMS 工作机制相比其他的垃圾收集器来说更复杂,整个过程分为 4 个阶段:
1)初始标记
只是标记一下 GC Roots 能直接关联的对象,速度很快,仍然需要暂停所有的工作线程。
2)并发标记
进行 GC Roots 跟踪的过程,和用户线程一起工作,不需要暂停工作线程。
3)重新标记
为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。
4)并发清除
清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作,所以总体上来看CMS 收集器的内存回收和用户线程是一起并发地执行。
G1 收集器
Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与 CMS 收集器,G1 收集器两个最突出的改进是:
- 基于标记-整理算法,不产生内存碎片。
- 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。
G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收集效率。