高级java工程师手把手教你解决内存不足引起JVM奔溃真实生产事故案例实战

高级java工程师手把手教你解决内存不足引起JVM奔溃案例实战

一、真实事故描述:

生产环境的Java程序进程,直接宕掉,进程都没有了,JVM奔溃了。生产事故,生产直接停止了,甲方爸爸客户着急了,公司老板奔溃了,恭喜你这个时候,压力转移到我这个高级工程师上了。马上解决是就是英雄,解决不了就滚蛋,这就是我的技术人生。生死存亡就看自己,与此同时很多人都在添油加醋,真正能解决问题的人,其实很少,多数其他人都是充数,在旁边叫唤,提出问题的人很多,解决问题的很少。

Java进程奔溃了,在重启。一会又奔溃了,起了又蹦,蹦了又重新启动,一般运维的思路就说如此。但是,核心的问题没有根本的解决。

二、解决问题的线索获取JVM奔溃日志

一般JVM奔溃,奔溃之前都会有JVM的日志,这种日志命名都是很佛系的。
日志位置是在当前执行JAVA的jar包同级目录
然后会出现一些有规律的日志,如下图呈现!

在这里插入图片描述

在这里插入图片描述
这种日志,每次JAVA程序奔溃一次,产生一个日志,并且是有时间戳标识,大家注意识别。

三、解读JVM奔溃的日志内容

#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 5242880 bytes for committing reserved memory.
# Possible reasons:
#   The system is out of physical RAM or swap space
#   The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap
# Possible solutions:
#   Reduce memory load on the system
#   Increase physical memory or swap space
#   Check if swap backing store is full
#   Decrease Java heap size (-Xmx/-Xms)
#   Decrease number of Java threads
#   Decrease Java thread stack sizes (-Xss)
#   Set larger code cache with -XX:ReservedCodeCacheSize=
#   JVM is running with Zero Based Compressed Oops mode in which the Java heap is
#     placed in the first 32GB address space. The Java Heap base address is the
#     maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress
#     to set the Java Heap base and to place the Java Heap above 32GB virtual address.
# This output file may be truncated or incomplete.
#
#  Out of Memory Error (os_linux.cpp:2749), pid=1181802, tid=0x00007f1b0fdfd700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_211-b12) (build 1.8.0_211-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode linux-amd64 compressed oops)
# Core dump written. Default location: /home/jk/core or core.1181802
#

---------------  T H R E A D  ---------------

Current thread (0x00007f1b38271800):  VMThread [stack: 0x00007f1b0fcfe000,0x00007f1b0fdfe000] [id=1181825]

Stack: [0x00007f1b0fcfe000,0x00007f1b0fdfe000],  sp=0x00007f1b0fdfc3f0,  free space=1016k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xad3455]  VMError::report_and_die()+0x2e5
V  [libjvm.so+0x4e0537]  report_vm_out_of_memory(char const*, int, unsigned long, VMErrorType, char const*)+0x67
V  [libjvm.so+0x910320]  os::pd_commit_memory(char*, unsigned long, unsigned long, bool)+0x100
V  [libjvm.so+0x90794f]  os::commit_memory(char*, unsigned long, unsigned long, bool)+0x1f
V  [libjvm.so+0x98c736]  PSVirtualSpace::expand_by(unsigned long)+0x56
V  [libjvm.so+0x98d9c8]  PSYoungGen::resize(unsigned long, unsigned long)+0xd8
V  [libjvm.so+0x98a166]  PSScavenge::invoke_no_policy()+0x1376
V  [libjvm.so+0x98a4fc]  PSScavenge::invoke()+0x4c
V  [libjvm.so+0x93a248]  ParallelScavengeHeap::failed_mem_allocate(unsigned long)+0x68
V  [libjvm.so+0xad4fa3]  VM_ParallelGCFailedAllocation::doit()+0x93
V  [libjvm.so+0xada1c6]  VM_Operation::evaluate()+0x46
V  [libjvm.so+0xad84fd]  VMThread::evaluate_operation(VM_Operation*) [clone .constprop.44]+0xcd
V  [libjvm.so+0xad8ae3]  VMThread::loop()+0x3a3
V  [libjvm.so+0xad8eb8]  VMThread::run()+0x78
V  [libjvm.so+0x90d952]  java_start(Thread*)+0x102

VM_Operation (0x00007f1aef4f5070): ParallelGCFailedAllocation, mode: safepoint, requested by thread 0x00007f1a78472000

奔溃的日志出奇一致,很明显内存不足,笔者这次案例很明显,找几个日志一致一样的报错,集中分析。笔者这次案例很明显,内存不足。之前的案例,有个IPV6的,可以去看我旧的文章!

结合看服务器状态综合分析

top

在这里插入图片描述


服务器状态很明显,虚拟内存饱满,物理内存不足,JAVA程序与其他服务争取内存资源,换来换去崩溃。

四、解决问题的思路与方法

既然问题已经定位了,怎么解决呢?生产环境,不能重启,又不能马上扩展物理内存。怎么办?
我给你的方案是,动态扩展服务器的虚拟内存方案。

方法如下:

一、查看当前虚拟内存的配置大小

free -h

在这里插入图片描述

二、创建swap文件

如果文件目录已经存在,则换个目录即可,也就是创建一个虚拟内存的页面文件!

cd /usr
mkdir swap
dd if=/dev/zero of=/usr/swap/swapfile bs=1M count=64096

提前保证路径下有剩余的空间
在这里插入图片描述

三、将目标设置为swap分区文件

mkswap /usr/swap/swapfile

在这里插入图片描述

chmod 0600 /usr/swap/swapfile       #改一下权限,系统建议0600

四、 启用swap分区文件

swapon /usr/swap/swapfile
free -h  #检查虚拟内存是否增加了

在这里插入图片描述

五、将虚拟内存的配置增加到开机自动启动配置

vim /etc/fstab         
/usr/swap/swapfile swap swap defaults 0 0  #将这个内容添加到上面的配置文件

在这里插入图片描述
保持文件退出
在这里插入图片描述

注意,现在是没有重启服务器情况下,临时增加了虚拟内存,解决了危机。生产环境,白天是不能紧急重启,如果重启,服务器也有可能起不来。所以才采用这种比较保守的方法。因为临时加内存条,也来不及!!

最终虚拟内存由之前的32G扩展到64G,页面文件有剩余,把JAVA服务,及其其他服务重启,问题暂时解决,周末的时候再扩展物理内存条。

最终总结:

笔者总结一下,JAVA的JVM奔溃,要先定位JVM的日志,而不是我们JAVA自身程序的日志。日志定位先正确。
作者是真实解决生产事故做一次真实案例,提供给JVM宕机网友们一个解决问题的思路与方法。希望写的东西能帮到你,如果真的帮到你了,记得给我点赞。
作者本人简介:现任国内某大型软件公司大数据研发工程师、MySQL数据库DBA,软件架构师。直接参与设计国家级亿级别大数据项目。并维护真实企业级生产数据库300余个。紧急处理数据库生产事故上百起,挽回数据丢失所操作的灾难损失不计其数。

在这里插入图片描述

在这里插入图片描述

  • 24
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术很渣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值