服务器JRE内存不足问题排查求助(系统内存充足)
Java程序向RabbitMQ推送消息时OOM问题排查指导
问题背景
在CentOS Linux服务器上运行Java程序向RabbitMQ推送信息时,程序因Out of Memory Error中断,日志内容较多,刚接触Java,需要排查方向指导。
相关错误日志
JVM内存分配失败日志
# Java运行时环境无法继续执行,内存不足。 # 本地内存分配(mmap)无法映射55574528字节以提交预留内存。 # 内存溢出错误 (os_linux.cpp:2795), pid=43653, tid=0x00007f46186b4700 # # JRE版本: OpenJDK Runtime Environment (8.0_332-b09) (build 1.8.0_332-b09) # Java虚拟机: OpenJDK 64-Bit Server VM (25.332-b09 混合模式 linux-amd64 压缩指针) # 无法生成核心转储。核心转储已禁用。要启用核心转储,请在再次启动Java前尝试执行 "ulimit -c unlimited" #
线程栈日志
--------------- 线程信息 --------------- 当前线程 (0x00007f46280ea000): VMThread [栈: 0x00007f46185b5000,0x00007f46186b5000] [id=43657] 栈: [0x00007f46185b5000,0x00007f46186b5000], sp=0x00007f46186b3330, 空闲空间=1016k 本地帧: (J=编译后的Java代码, j=解释执行代码, Vv=虚拟机代码, C=本地代码) V [libjvm.so+0xb65ecd] VMError::report_and_die()+0x1cd V [libjvm.so+0x5075aa] report_vm_out_of_memory(char const*, int, unsigned long, VMErrorType, char const*)+0xaa V [libjvm.so+0x941588] os::pd_commit_memory(char*, unsigned long, unsigned long, bool)+0xd8 V [libjvm.so+0x938d9e] os::commit_memory(char*, unsigned long, unsigned long, bool)+0x2e V [libjvm.so+0x9b902b] PSVirtualSpace::expand_by(unsigned long)+0x5b V [libjvm.so+0x9a90ca] PSOldGen::expand_by(unsigned long) [clone .part.113]+0x2a V [libjvm.so+0x9a929b] PSOldGen::expand(unsigned long) [clone .part.115]+0xdb V [libjvm.so+0x9a9be8] PSOldGen::resize(unsigned long)+0x198 V [libjvm.so+0x9af58c] PSParallelCompact::invoke_no_policy(bool)+0x9dc V [libjvm.so+0x9b6b7d] PSScavenge::invoke()+0x17d V [libjvm.so+0x968c73] ParallelScavengeHeap::failed_mem_allocate(unsigned long)+0x63 V [libjvm.so+0xb67b23] VM_ParallelGCFailedAllocation::doit()+0x93 V [libjvm.so+0xb6cfe5] VM_Operation::evaluate()+0x55 V [libjvm.so+0xb6afaa] VMThread::evaluate_operation(VM_Operation*)+0x11a V [libjvm.so+0xb6b419] VMThread::loop()+0x219 V [libjvm.so+0xb6b8d2] VMThread::run()+0x92 V [libjvm.so+0x93e4f2] java_start(Thread*)+0xf2 虚拟机操作 (0x00007f463172d3e0): ParallelGCFailedAllocation, 模式: 安全点, 由线程 0x00007f4628063800 请求
系统内存信息
--------------- 系统信息 --------------- 操作系统:CentOS Linux release 7.8.2003 (Core) uname:Linux 3.10.0-1160.62.1.el7.x86_64 #1 SMP Tue Apr 5 16:57:59 UTC 2022 x86_64 libc:glibc 2.17 NPTL 2.17 资源限制: 栈大小 8192k, 核心转储大小 0k, 最大进程数 4096, 最大文件句柄数 4096, 地址空间无限制 系统负载:4.81 6.40 3.68 /proc/meminfo: 总内存: 3861256 kB 空闲内存: 108460 kB 可用内存: 19104 kB 缓冲区: 0 kB 缓存: 22388 kB 交换缓存: 7600 kB 活跃内存: 2577112 kB 非活跃内存: 971876 kB 活跃匿名内存: 2570780 kB 非活跃匿名内存: 957160 kB 活跃文件内存: 6332 kB 非活跃文件内存: 14716 kB 不可回收内存: 0 kB 锁定内存: 0 kB 总交换空间: 1048572 kB 空闲交换空间: 780 kB 脏页: 20 kB 回写页: 0 kB 匿名页: 3519584 kB 映射页: 3356 kB 共享内存: 1184 kB Slab内存: 85128 kB 可回收Slab: 40496 kB 不可回收Slab: 44632 kB 内核栈: 7872 kB 页表: 20908 kB NFS不稳定页: 0 kB Bounce页: 0 kB 回写临时页: 0 kB 提交限制: 2979200 kB 已提交地址空间: 3444760 kB 虚拟内存总量: 34359738367 kB 已用虚拟内存: 183428 kB 虚拟内存空闲块: 34359310332 kB 每个CPU内存: 24064 kB 硬件损坏内存: 0 kB 匿名大页: 448512 kB CMA总内存: 0 kB CMA空闲内存: 0 kB 大页总数: 0 空闲大页: 0 预留大页: 0 超额大页: 0 大页大小: 2048 kB 直接映射4k: 94016 kB 直接映射2M: 4100096 kB 直接映射1G: 2097152 kB
内存情况分析
你看到的MemFree(108460KB)只是系统未被使用的内存,但实际可用内存要看MemAvailable(仅19104KB),这个值才是系统能分配给新应用或扩展现有应用的内存。同时:
- 交换空间
SwapFree只剩780KB,几乎耗尽,系统无法通过交换释放内存 Committed_AS(3444760KB)已经超过CommitLimit(2979200KB),说明系统已提交的内存总量超过了内核允许的上限,这会直接导致内存分配失败
排查方向
- 检查JVM内存参数配置:查看启动Java程序时的
-Xmx(最大堆内存)、-Xms(初始堆内存)参数。如果-Xmx设置过大,超过系统MemAvailable,会导致JVM无法扩展堆内存;建议将-Xms和-Xmx设为相同值,避免JVM频繁扩容堆内存。 - 排查内存泄漏:程序向RabbitMQ推送消息时,可能存在消息对象未及时释放、连接/通道未关闭、队列堆积等情况。可以通过以下方式分析:
- 开启GC日志:添加
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps参数,查看GC频率和内存回收情况 - 使用
jmap工具生成堆转储文件:执行jmap -dump:format=b,file=heapdump.hprof <pid>,分析哪些对象占用大量内存
- 开启GC日志:添加
- 清理系统内存压力:使用
top或htop命令查看其他进程的内存占用情况,关闭不必要的进程释放内存;如果系统长期内存不足,考虑升级服务器内存。 - 调整GC策略:当前使用的是ParallelScavenge收集器,老年代扩展失败说明GC无法有效回收内存。可以尝试调整GC参数,比如增大老年代比例(
-XX:NewRatio=2),或者更换为CMS收集器(-XX:+UseConcMarkSweepGC),减少GC停顿时间和内存碎片。
内容的提问来源于stack exchange,提问作者Robin wong
相关产品推荐
相关产品推荐

