堆内存持续占用高 且 ygc回收效果不佳” 排查处理实践

说明:部分素材来源于网络,数据分析全为真实数据。

一、 问题背景

自建的两套工具,运行一段时间后均出现 内存占用高触发报警,频繁young gc且效果不佳。曾经尝试多次解决,因各种原因耽搁,最近下定决心处理此问题。

二、 问题描述

Q:堆内存1018M,使用达到950M左右触发一次young gc,ygc之后内存占用630M,未发生full gc



三、 容器配置

已处理关键信息

•主机名 xxx

•实例ID xxx

•ip

•操作系统名称Linux

•操作系统体系结构amd64

•CPU个数2

•JRE版本1.8.0_191

•JVM启动时间2023-02-18 17:14:10.873

•启动路径/export/App

•Full GCPS MarkSweep

•Young GCPS Scavenge

•进程ID115135

•物理内存大小251.4GB(269888389120Byte)

•交换区大小0.0GB(0Byte)

•虚拟内存大小12.5GB(13368197120Byte)

•应用路径/export/App/lib/tp-center-web.jar!/BOOT-INF/lib/

•JVM启动参数-javaagent:/export/xxx/lib/pfinder-profiler-agent-1.0.8-20210322032622-6f12bda2.jar -Ddeploy.app.name=xxx -Ddeploy.app.id=xxx -Ddeploy.instance.id=0 -Ddeploy.instance.name=server1 -DJDOS_DATACENTER=HT -Dloader.path=./conf -Dspring.profiles.active=pre -Xms1024m -Xmx1024m -Xmn384m -XX:MetaspaceSize=64m -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly -XX:ParallelGCThreads=2 -XX:CICompilerCount=2 -XX:MaxDirectMemorySize=128m -Duser.timezone=Asia/Shanghai -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=xxx -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=xxx

四、 问题分析

1、 young gc的时机?

R:ygc在新生代的eden区满了之后就会触发,采用复制算法回收新生代的垃圾。

2、 为何young gc后堆内存使用率仍然很高?

R:新生代过小,大对象直接进入老年代,编码时要尽量减少大对象的使用。

3、 full gc 的时机?

R:HotSpot VM里,除了CMS之外,其它能收集老年代的GC都会同时收集整个GC堆,包括新生代

1) 发生fgc之前进行检查,如果 老年代可用的连续内存空间 < 新生代历次ygc后升入老年代的对象总和的平均大小,此时先触发old gc,然后执行ygc

2) 执行ygc之后有一批对象需要放入老年代,此时老年代没有足够空间存放对象,必须触发一次ogc

3) 老年代内存使用率超过阈值,也要触发ogc

4) 元空间不足时也会触发一次

4、 什么原因导致内存占用高?

R:heap dump分析、gc日志

五、 回收器

•吞吐量优先(Parallel Scavenge):新生代收集器,侧重于吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+运行垃圾收集时间))的控制。

•Serial Old:Serial Old是Serial收集器的老年代版本, 它同样是一个单线程收集器, 使用标记-整理算法:由于老年代 Serial Old 收集器在服务端应用性能上的“拖累”, 使用Parallel Scavenge 收集器也未必能在整体上获得吞吐量最大化的效果。由于单线程的老年代收集中无法充分利用服务器多处理器的并行处理能力, 在老年代内存空间很大而且硬件规格比较高级的运行环境中, 这种组合的总吞吐量甚至不一定比ParNew加CMS的组合来得优秀。

•Parallel Old :是 Parallel Scavenge 收集器的老年代版本, 支持多线程并发收集, 基于标记-整理算法实现. 这个收集器是直到 JDK 6 时才开始提供的, 在此之前, 新生代的 Parallel Scavenge收集器一直处于相当尴尬的状态, 原因是如果新生代选择了 Parallel Scavenge 收集器, 老年代除了 Serial Old(PS MarkSweep)收集器以外别无选择

UseParallelGC: JDK9 之前虚拟机运行在 Server 模式下的默认值, 使用 ParallelScavenge + Serial Old(PS MarkSweep)的收集器组合进行内存回收。

UseParallelOldGC: 打开此开关后, 使用 Parallel Scavenge + Parallel Old 的收集器组合进行内存回收。

•ParNew收集器与Parallel收集器类似:此收集器是许多运行在Server模式下的虚拟机的首选,除了Serial收集器外,只有它能与CMS收集器配合工作

•并发标记清除(CMS)回收器:是一种以获取最短回收停顿时间为目标的回收器,该回收器是基于“标记-清除”算法实现的。注重回收时产生的停顿时间,是停顿时间最短的收集器。非常适合注重用户体验的应用上,是Hotspot虚拟机第一款真正意义上的并发收集器,第一次实现了让垃圾收集线程与用户线程几乎同时运行

六、 优化策略

1、 加gc日志

-XX:+PrintGCDetails // 创建详细的gc日志

-XX:+PrintGCTimeStamps

-Xloggc:/export/Logs/com/gc.log // gc日志文件名

-XX:+U

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值