垃圾收集器

经典垃圾收集器

默认情况下:
老年代占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虚拟机>>

posted @ 2020-09-01 12:42  多放点香菜  阅读(71)  评论(0)    收藏  举报