Java 17+ZGC程序长期暂停恢复后出现OutOfMemoryException求助
问题描述
我的应用线程结构如下:
Main Thread -> ScheduleAtFixedRate1 -> ScheduleAtFixedRate3 -> ScheduleAtFixedRate4 -> ScheduleAtFixedRate2
- 主线程(含main方法)启动
ScheduleAtFixedRate1和ScheduleAtFixedRate2两个定时任务;ScheduleAtFixedRate1又启动ScheduleAtFixedRate3和ScheduleAtFixedRate4两个定时任务。 ScheduleAtFixedRate2定时向服务器请求数据,返回结果包含控制程序暂停的pause变量:当pause=true时,ScheduleAtFixedRate1调用close(true)关闭ScheduleAtFixedRate3和ScheduleAtFixedRate4,此后仅检查pause状态,不再执行完整代码块。- 程序以JVM参数
-XX:+UseZGC启动,基于Java 17运行,日常运行状态正常,内存分配2GB,平均占用约800MB。 - 异常现象:程序被长时间暂停(数小时)后恢复,
ScheduleAtFixedRate1重启ScheduleAtFixedRate3和ScheduleAtFixedRate4,短暂运行后因thread-x抛出OutOfMemoryException崩溃;短暂暂停(数分钟)无此问题,暂停时间越长崩溃概率越高,偶发崩溃。 - 推测:ZGC在长期暂停后未正常工作,但不知如何解决,无法共享项目代码。
排查与解决方向
1. 确认定时任务关闭的彻底性
- 检查
close(true)是否真正终止了ScheduleAtFixedRate3和ScheduleAtFixedRate4的线程,是否存在线程未被正确中断、任务队列残留大量未执行任务的情况。长期暂停期间,若任务队列持续堆积,恢复后短时间内大量任务执行可能瞬间占用过高内存。 - 验证
ScheduleAtFixedRate1在pause=true时是否完全停止了新任务的提交,避免恢复前已有大量待执行任务积压。
2. 监控ZGC在暂停前后的状态
- 启用ZGC的日志记录,添加JVM参数:
-Xlog:gc*=info:file=zgc.log:time,uptime,重点查看长期暂停恢复后的GC行为,确认是否存在GC停顿过长、内存回收不及时、对象晋升异常的情况。 - 检查恢复后内存占用的变化曲线,确认是否是短时间内内存暴涨超出2GB限制,而非ZGC本身失效。
3. 排查内存泄漏点
- 暂停期间,
ScheduleAtFixedRate2仍在运行(假设未被暂停),是否存在持续创建对象但未被回收的情况?比如请求结果的缓存未清理、全局集合持续累积数据。 - 恢复时重启
ScheduleAtFixedRate3和ScheduleAtFixedRate4,是否存在重复创建资源(如连接池、缓存实例)导致的内存叠加?
4. 调整ZGC相关参数
- 尝试添加
-XX:ZCollectionInterval=60(设置GC触发间隔为60秒),强制ZGC定期回收,避免暂停期间内存堆积过多。 - 调整
-XX:ZHeapMaxSize=2g明确最大堆内存,同时检查是否存在堆外内存占用过高的情况(可添加-XX:NativeMemoryTracking=summary监控堆外内存)。
5. 验证线程恢复逻辑
- 检查
ScheduleAtFixedRate1重启任务时,是否对之前的任务实例做了完全清理?是否存在旧实例未被GC回收,与新实例同时占用内存的情况?
内容的提问来源于stack exchange,提问作者KunLun
相关产品推荐
相关产品推荐

