Java SpringBoot服务运行内存持续升高无报错宕机问题排查咨询
内存利用率突然飙升的可能原因
- 直接内存(Direct ByteBuffer)泄漏:如果业务逻辑用到大量NIO操作、Netty框架或者
Unsafe分配的堆外内存,这部分内存不受JVM堆参数限制,也不会出现在常规heap dump中。数据看板的批量数据处理、IO传输场景下,频繁分配直接内存却没有主动释放,很容易出现占用后无法回落的问题。可添加JVM参数-XX:MaxDirectMemorySize限制最大直接内存,超出时会抛出OOM异常方便定位,也可以开启NativeMemoryTracking参数追踪堆外内存分配情况。 - Metaspace内存泄漏:如果服务使用了大量动态代理(如Spring AOP、动态生成字节码的框架)、热部署插件,或者频繁加载重复类定义,Metaspace的占用会持续上涨不释放。若没有配置
-XX:MaxMetaspaceSize,JVM会默认占用系统内存直到上限,这部分占用也不会在常规堆内存泄漏排查中体现,可先打印Metaspace占用曲线确认是否和整体内存上涨趋势匹配。 - 线程栈内存泄漏:并发请求峰值时如果服务创建了大量未销毁的线程,每个线程默认栈内存为1MB(可通过
-Xss调整),峰值时创建上万个线程仅栈内存就可占用十几GB。如果线程池核心参数配置不合理(如核心线程数过大、阻塞队列无界)、存在线程死锁,都会导致线程持续占用内存不释放,可先统计服务运行时的线程数量变化,排查是否存在线程数突增的情况。 - 操作系统PageCache占用:如果后端数据处理逻辑存在大量本地文件读写、大文件下载操作,操作系统会将读写过的文件内容放入PageCache,这部分内存会被计入进程RSS占用,看起来和服务内存上涨表现一致。默认系统会在内存不足时自动回收PageCache,但如果内核参数配置不合理、服务被设置了cgroups内存限制,可能出现PageCache未及时回收就触发OOM Killer杀掉进程的情况,这种场景下进程本身不会输出错误日志,只会在系统
/var/log/messages中留下OOM相关记录。 - 第三方Native依赖内存泄漏:如果用到了包含Native代码的第三方依赖(如图像处理、数据压缩、加密算法类库),这些库自身的内存泄漏不受JVM内存管理机制回收,也不会出现在heap dump和常规Native内存检测结果中,可对比内存飙升时间段的接口调用量,确认是否和调用依赖Native库的接口请求量正相关。
- GC触发时机配置不合理:如果JVM的GC策略配置不当(如老年代回收阈值设置过高、使用低延迟GC时软引用回收策略配置过松),大量长期存活的对象进入老年代后一直未触发Full GC,会导致堆内存占用持续走高。可主动执行
jmap -histo:live命令触发一次Full GC,观察执行后系统内存是否回落,如果回落即可确认是GC触发时机的问题。
内容的提问来源于stack exchange,提问作者mohan p
相关产品推荐
相关产品推荐

