GC日志参数和垃圾收集器

GC日志打印相关

参数说明
-XX:PrintGCDetails开启gc日志打印
-Xloggc:{path}/gc.log输出gc日志到指定路径文件
-Xloggc:{path}/gc.%t.logjava8以后可以用%p,%t占位符来指定gc输出文件,%p:进程pid;%t:启动时间戳
-XX:+UseGCLogFileRotation启动日志循环打印
-XX:NumberOfGClogFiles=5会滚动覆盖旧的gc日志,只保留最新的5个
-XX:GCLogFileSize = 2M设置每个GC日志最大为2M
-XX:+PrintGCDateStamps增加具体时间输出

垃圾收集器:

参数说明
-XX:+UseSerialGC开启串行垃圾收集器
-XX:+UseParallelGC开启并行垃圾收集器
-XX:+UseConcMarkSweepGC开启CMS垃圾收集器
-XX:+UseG1GC开启G1垃圾收集器

并行:多个线程并行进行垃圾收集,用户线程会暂停
并发:用户线程和垃圾收集线程交替运行,用户线程不会停止

-XX:+UseSerialGC(串行垃圾收集器)
串行垃圾收集器,client的模式jvm下默认的垃圾收集器,单线程做垃圾收集,会触发全线STW,停止所有用户线程。年轻代使用mar-copy(标记-复制)算法,老年代使用mark-sweep-compact(标记-清除-整理)算法

-XX:+UseParallelGC(并行垃圾收集器)
并行垃圾收集器,吞吐量优先,垃圾收集时候用户线程暂停,多个线程同时并行进行垃圾收集来减少GC时间。年轻代使用mar-copy(标记-复制)算法,老年代使用mark-sweep-compact(标记-清除-整理)算法。
可以通过命令行参数-XX:ParallelGCThreads=N来指定 GC 线程数, 其默认值为CPU核心数。

-XX:+UseConcMarkSweepGC (CMS垃圾收集器)
使用CMS,那么年轻代默认使用UseParNewGC收集器,老年代使用CMS。CMS是并发垃圾收集器,垃圾除了初始标记和重新标记阶段,其他阶段垃圾线程都是和用户线程并发得在执行。

两个特点,来避免老年代垃圾收集时候出现长时间停顿:

  • 不对老年代进行整理,而是使用空闲列表(free-lists)来管理内存空间的回收
  • 在 mark-and-sweep (标记-清除) 阶段的大部分工作和应用线程一起并发执行

CMS垃圾回收得几个阶段:

  1. 初始标记(标记GCRoot和GCRoot直接引用的对象,此过程Stop-the-world
  2. 并发标记(遍历老年代,标记所有存活对象,从初始标记的对象往下可达性标记)
  3. 并发预清理(处理应用发生变化的对象,如果在并发标记过程中引用关系发生了变化,JVM会通过“ Card(卡片) ”的方式将发生了改变的区域标记为“脏”区,脏区所引用的对象也会被标记为可达对象)
  4. 最终标记(此过程Stop-the-world,防止引用关系发生变化)
  5. 并发清除(清除所有不再使用的对象,回收内存)
  6. 并发重置(重置CMS算法相关内部数据,为下一次GC做准备)

-XX:+UseG1GC(G1垃圾收集器)

G1适合大内存,需要较低的延迟场景.。一般超过8G以上的大堆比较建议使用G1

G1垃圾收集器最大特点是,堆空间不再是划分为整块的young区、old区而是划分为许多的Region(默认是2048块)。然后一部分region组成end区,一部分组合成old区,一部分组合成Survive区。这样划分之后,使得 G1不必每次都去收集整个堆空间,而是以增量的方式来进行处理: 每次只处理一部分内
存块,称为此次GC的回收集(collection set)。

垃圾最多的小块会被优先收集

在这里插入图片描述
上图还省略了一个H区(大对象区),在一个对象大小超过region50%时候,会被分配到H区

G1有几个很重要的参数:

  • -XX:+UseG1GC :启用G1 GC;
  • -XX:+InitiatingHeapOccupancyPercent :决定什么情况下发生G1 GC;
  • -XX:MaxGCPauseMills :期望每次GC暂定的时间,比如我们设置为50,则G1 GC会通过调节每次GC的操作时间,尽量让每次系统的GC停顿都在50上下浮动。如果某次GC时间超过50ms,比如说100ms,那么系统会自动在后面动态调整GC行为,围绕50毫秒浮动。

mixed GC:并发标记完成之后,G1将执行一次mixed GC,就是不只清理年轻代,还将一部分老年代区域也加入到 回收集 中。

Remembered Set :每个region都有一个 Remembered Set ,列出了从外部指向本块的所有引用,这样在回收一个小堆块时候,不用便利整个堆来确定他们的存活性

G1 Full GC:G1里如果发生了full GC,那么会退化为串行GC,停顿时间达到秒级,我们尽可能要避免这种情况的发生。

  • 并发模式失败:G1启动标记周期,但在Mix GC之前,老年代就被填满,这时候G1会放弃标记周期。这种情形下,需要增加堆大小,或者调整周期(例如增加线程数-XX:ConcGCThreads等)。
  • 晋升失败或者疏散失败:G1在进行GC的时候没有足够的内存供存活对象或晋升对象使用,由此触发了Full GC。可以在日志中看到(to-space exhausted)或者(to-space overflow)。解决这种问题的方式是:
    a. 增加 -XX:G1ReservePercent 选项的值(并相应增加总的堆大小),为“目标空间”增加预留内存量。
    b. 通过减少 -XX:InitiatingHeapOccupancyPercent 提前启动标记周期。
    c. 也可以通过增加 -XX:ConcGCThreads 选项的值来增加并行标记线程的数目。
  • 巨型对象分配失败:当巨型对象找不到合适的空间进行分配时,就会启动Full GC,来释放空间。这种情况下,应该避免分配大量的巨型对象,增加内存或者增大-XX:G1HeapRegionSize,使巨型对象不再是巨型对象。

总结
具体使用什么垃圾收集器看实际情况而定,例如:

  • 如果系统考虑吞吐优先,CPU资源都用来最大程度处理业务,用Parallel GC
  • 如果系统考虑低延迟有限,每次GC时间尽量短,用CMS GC;
  • 如果系统内存堆较大,同时希望整体来看平均GC时间可控,使用G1 GC
  • 如果可以使用jdk11,大堆,又要求GC停顿时间很短,可以使用ZGC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值