Linux开发虚拟机配置较大初始堆时Java进程无法启动、频繁被OOM终止求助
直接定位根因
看你贴的free -h输出,异常点非常明确:
shared 4.6G
Linux 的free命令中,shared列指代不可被系统自动回收的共享内存,绝大多数场景下来源于tmpfs文件系统(最常见的是默认挂载的/dev/shm)。
你看到的free + buff/cache ≈5G是虚的:这5G里有4.6G已经是被tmpfs占用的、不能释放的内存,真正能给新进程用的只有available列显示的328M,远不够JVM申请1G堆内存的需求,自然会报Cannot allocate memory。
常规排查不到问题,是因为普通内存查看方法不会单独把tmpfs的不可回收占用列出来,很容易被buff/cache的高数值误导。
快速验证步骤
- 先查默认共享内存目录的状态:执行
df -h /dev/shm,大概率会看到容量被预设成了总内存的一半甚至更高,哪怕目录里没放几个文件,也会占用对应的内存配额。 - 再查所有tmpfs挂载:执行
mount -t tmpfs,确认有没有异常挂载的大尺寸tmpfs(比如被误挂载到业务日志、数据目录的tmpfs),或者多个服务往tmpfs写了大文件没清理。 - 如果机器上跑了Docker/K8s容器,额外执行
docker ps -q | xargs docker inspect --format '{{.Name}} {{.HostConfig.ShmSize}}',检查每个容器的共享内存配额,很多人会手动把容器的/dev/shm设到几G,多跑几个就会吃掉大量shared内存。
解决方法
- 临时应急:如果
/dev/shm里没有正在使用的文件,直接执行rm -rf /dev/shm/*清空,shared内存会立刻释放,马上就能启动JVM。 - 永久修复:如果不需要用共享内存,修改
/etc/fstab里tmpfs的挂载行,把默认的size=50%参数(多数虚拟机镜像默认设为总内存的50%)改成实际需要的大小,比如size=512M,重启后生效。 - 多台虚拟机都出同样问题的话,直接找运维同步调整虚拟机镜像的tmpfs默认配置即可,不用怀疑物理宿主机故障。
内容的提问来源于stack exchange,提问作者leowangzz
相关产品推荐
相关产品推荐

