java垃圾回收算法和经典垃圾收集器

待我称王封你为后i 2024-03-02 08:16 184阅读 0赞

主要总结jvm中的垃圾收集算法和垃圾收集器

文章目录

  • 一、jvm实用工具
    • 1.查看和修改jvm配置
    • 2.使用MAT工具打开后发现占用内存很少
  • 二、垃圾收集算法
    • 1.标记-清除算法
    • 2.标记-复制算法
    • 3.标记-整理算法
  • 三、垃圾收集器
    • 新生代收集器
      • 1.Serial
      • 2.ParMew
      • 3.Parallel Scavenge
    • 老年代收集器
      • 1.Serial Old
      • 2.Parallel Old
      • 3.CMS
    • 混合收集器
      • 1.G1

垃圾收集算法:
标记-清除算法
标记-复制算法
标记-整理算法


一、jvm实用工具

1.查看和修改jvm配置

  1. # 查看14进程的所有jvm配置
  2. jinfo -flags 14
  3. # 查看某一项配置,比如查看dump文件路径
  4. jinfo -flag HeapDumpPath 14
  5. # 增加gc日志打印相关的jvm配置(删除则使用-号)
  6. jinfo -flag +PrintGC 14 // 开启gc日志
  7. jinfo -flag +PrintGCDetails 14 // 打印详情
  8. jinfo -flag +PrintGCDateStamps 14 // 格式化时间
  9. jinfo -flag +HeapDumpBeforeFullGC 14 // fgc前dump
  10. jinfo -flag HeapDumpPath=/logs/dump_xxx.bin 14 // 设置dump路径
  11. 如果不清楚具体的配置项的名称,可以通过以下命令进行过滤查找(以下manageable为关键字):
  12. java -XX:+PrintFlagsFinal -version | grep manageable

2.使用MAT工具打开后发现占用内存很少

  1. 默认不显示不可达对象。打开MAT的设置,reference,保留不可达的对象。如果实时设置不生效,尝试重新打开dump文件。

二、垃圾收集算法

1.标记-清除算法

2.标记-复制算法

3.标记-整理算法

三、垃圾收集器

垃圾收集器也分为新生代收集器和老年代收集器,目前比较常用的有以下,在jvm运行时几乎也都是两个收集器同时配置运行:
经典的垃圾收集器

新生代收集器

1.Serial

最基础、历史最悠久的收集器。曾经在1.3是HotSpot新生代收集器的唯一选择。
采用复制算法。
生产组合:Serial/Serial Old

2.ParMew

实质上是Serial收集器的多线程并行版本,很多Serial收集器的jvm控制参数、算法、分配规则等也都完全一致。
采用复制算法。
生产组合:ParNew/Serial Old
ParNew/CMS

3.Parallel Scavenge

一款新生代收集器,基于标记-复制算法实现,也是能够并行收集的多线程收集器。CMS等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(throughput),也被称为“吞吐量优先收集器”。
吞吐量 = 运行用户代码时间 / 运行用户代码时间 + 运行垃圾收集时间
生产组合:Parallel Scavenge / Parallel Old

总结:新生代收集器常用复制算法

老年代收集器

1.Serial Old

作为Serial收集器的老年代版本,是一个单线程收集器,使用标记-整理算法。
生产组合:Serial/Serial Old

2.Parallel Old

是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现,1.6才开始提供。
生产组合:Parallel Scavenge / Parallel Old

3.CMS

CMS(Concurrent Mark Swep)并发-标记-清除收集算法是一种以获取最短回收停顿时间为把目标的收集器,是1.8版本常用的老年代回收器。
整个垃圾清理过程主要分为四步:

  • 初始标记(CMS Initial Mark)
  • 并发标记 CMS-concurrent
  • 重新标记(CMS Final Remark)
  • 并发清除CMS-concurrent-sweep
    在打印出GC日志可以观察到如下GC过程:

    2023-09-15T16:58:11.672+0800: [GC (CMS Initial Mark) [1 CMS-initial-mark: 643954K(701184K)] 661721K(777920K), 0.0067740 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
    2023-09-15T16:58:11.678+0800: [CMS-concurrent-mark-start]
    2023-09-15T16:58:11.853+0800: [GC (Allocation Failure) 2023-09-15T16:58:11.853+0800: [ParNew: 75932K->8512K(76736K), 0.0570174 secs] 719886K->678318K(777920K), 0.0571620 secs] [Times: user=0.06 sys=0.00, real=0.06 secs]
    2023-09-15T16:58:11.989+0800: [CMS-concurrent-mark: 0.252/0.310 secs] [Times: user=0.50 sys=0.00, real=0.31 secs]
    2023-09-15T16:58:11.989+0800: [CMS-concurrent-preclean-start]
    2023-09-15T16:58:11.995+0800: [CMS-concurrent-preclean: 0.006/0.006 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
    2023-09-15T16:58:11.995+0800: [CMS-concurrent-abortable-preclean-start]
    2023-09-15T16:58:12.347+0800: [CMS-concurrent-abortable-preclean: 0.052/0.352 secs] [Times: user=0.10 sys=0.01, real=0.36 secs]
    2023-09-15T16:58:12.349+0800: [GC (CMS Final Remark) [YG occupancy: 32938 K (76736 K)]2023-09-15T16:58:12.349+0800: [Rescan (parallel) , 0.0162113 secs]2023-09-15T16:58:12.365+0800: [weak refs processing, 0.0027552 secs]2023-09-15T16:58:12.368+0800: [class unloading, 0.1680965 secs]2023-09-15T16:58:12.536+0800: [scrub symbol table, 0.0499563 secs]2023-09-15T16:58:12.586+0800: [scrub string table, 0.0075458 secs][1 CMS-remark: 669806K(701184K)] 702744K(777920K), 0.2450178 secs] [Times: user=0.23 sys=0.01, real=0.24 secs]
    2023-09-15T16:58:12.594+0800: [CMS-concurrent-sweep-start]
    2023-09-15T16:58:12.770+0800: [CMS-concurrent-sweep: 0.176/0.176 secs] [Times: user=0.30 sys=0.03, real=0.18 secs]
    2023-09-15T16:58:12.770+0800: [CMS-concurrent-reset-start]
    2023-09-15T16:58:12.772+0800: [CMS-concurrent-reset: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

jinfo -flags 15命令查询结果可以看到CMS的配置默认和ParNew组合使用:
在这里插入图片描述
生产组合:ParNew/CMS

混合收集器

1.G1

在G1出现之前,垃圾收集的目标范围要么是整个新生代(Minor GC),要么是整个老年代(Major GC),再要么就是整个java堆(Full GC)。而G1收集器是面向堆内存任何部分来组成回收集进行回收,衡量标准不是属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器的Mixed GC模式。

G1将连续的java堆划分为多个大小相等的独立区域(Region),每个region都可以根据需要扮演新生代的Eden空间,Survivor空间或者老年代空间。

Region中还有一类特殊的Humongous区域,抓门用来存储大对象。G1认为只要大小超过一个Region容量一半的对象即可判定为大对象。

从整体上来看G1是基于“标记-复制算法”实现,但从局部(两个Region)之间上看又是基于“标记-整理”算法实现的,但都意味着G1运行期间不会产生内存空间碎片。

在这里插入图片描述

其他垃圾收集器:

  1. Shenandoah(低延时收集器)
  2. ZGC(低延时收集器,jdk11加入,基于Region,使用了读屏障、染色指针、内存多重映射等技术实现可并发的标标记-整理算法的)
  3. Epsilon

发表评论

表情:
评论列表 (有 0 条评论,184人围观)

还没有评论,来说两句吧...

相关阅读