垃圾收集器
经典垃圾收集器
默认情况下:
老年代占2/3的堆空间
新生代占1/3的堆空间
收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的实践者
Serial收集器
从名字就可以看出来是串行单线程收集器,但是这个单线程不仅仅是说明它会使用一条收集线程去工作,而是强调它在进行垃圾收集的时候,必须暂停其他所有工作线程,直到它收集结束。
优点:简单高效,适合运行在客户端
新生代采用复制算法
ParNew收集器
实质上是Serial的多线程版本
新生代采用复制算法
Parallel Scavenge收集器
基于标记-复制算法的多线程收集器,从表面上看和ParNew没有区别,但是实际上这款垃圾收集器与其他收集器的关注点不同,关注的是吞吐量
提供了两个参数用于精确控制吞吐量,一个是控制最大垃圾收集时间,一个是直接控制吞吐量的大小
吞吐量=$\frac {运行用户代码时间}{运行用户代码时间+运行垃圾收集器时间}$
Serial Old收集器
单线程收集器,Serial的老年代版本
采用标记-整理算法
也是供给客户端模式下使用的
Parallel Old收集器
基于标记-整理算法
CMS收集器
以获取最短停顿时间为目标的收集器
基于标记-清除算法
面向服务器端的
是真正第一款实现并发收集器,第一次实现了用户线程和收集线程并发执行
主要有四个阶段:
-
初始标记
-
并发标记
-
重新标记
-
并发清除
初始标记和重新标记是需要暂停用户线程的,但是所需时间远远比并发标记时间短。
三个缺点: -
对系统资源敏感,因为是多线程,所以不可避免的占用了一些系统资源导致应用程序变慢,降低吞吐量
-
无法处理“浮动垃圾”,并发清理过程是和用户线程并发执行的,所以还是会有新的垃圾对象产生,但是这部分垃圾对象是出现在标记过程以后的,CMS无法立即处理,只能留到下一次GC
-
既然是标记-清除算法,那么肯定会有内部碎片化问题
G1收集器
一款面向服务器端的垃圾收集器
G1面向了堆内存的任何部分来组成回收集进行回收,衡量标准不是属于哪一代,而是看哪块内存中存放的垃圾数量比较多,回收利益最大
G1不再坚持固定大小以及固定数量分代区域划分,而是把连续的java堆划分为多个大小相等的独立区域,region区。每个region都可以根据需要扮演不同的分代区域
还有一个比较特殊的区域,专门存储大对象,衡量标准就是这个对象的大小超过region的一半即可判定为大对象
具体是让G1收集器跟踪各个Region里面的垃圾堆积的“价值”大小,价值就是回收所获得的空间大小以及回收所需时间的经验值,然后再后台维护一个优先级列表,在用户设定的允许的收集时间内优先处理价值收益最大的region
分为四个阶段:
- 初始标记:标记一下GC Roots能直接关联的对象,并且修改一些指针的值,使并发标记阶段用户线程能够正确的在可用的region中分配新对象[暂停]
- 并发标记:进行可达性分析
- 最终标记:对用户线程做另一个短暂的暂停,用于处理并发阶段结束后遗留下的少量的[暂停]
- 筛选回收:对各个Region的回收价值和成本进行排序,然后根据用户设定的参数停顿时间来指定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那部分Region的存活对象复制到新的Region中,再清理掉整个旧的Region的全部空间。[暂停]
参考:
图源网络
<<深入理解Java虚拟机>>

浙公网安备 33010602011771号