Java进程 OOM的多种情况

java,进程,oom,多种,情况 · 浏览次数 : 331

小编点评

# Out of memory: Kill process 25813 ## 问题的分析 1. GC日志没有Full GC多次出现的现象。 2. 之前系统多次出现过swap分区使用过多的情况。导致卡顿。为了避免过于卡顿影响业务,已经将swap分区关闭。 3. dmesg发现系统经常有OOM的情况。所以分析下来,在不特备影响系统性能的情况下只有两种解决策略: 1. 适当降低jvm的堆区, 也就是降低 -Xms和-Xmx 给其他使用者空闲出来一部分资源.2. 提高资源配置. 加大内存, 避免出现宕机的问题. ## 解决方案 1. 降低jvm的堆区,降低 -Xms和-Xmx 给其他使用者空闲出来一部分资源。 2. 提高资源配置,增加内存,避免出现宕机问题。 3. 减少swap分区的使用,关闭swap分区,降低OOM的频率。 ## 总结 1. 在不特备影响系统性能的情况下,只有两种解决策略。 2. 降低jvm的堆区,降低 -Xms和-Xmx 给其他使用者空闲出来一部分资源。 3. 提高资源配置,增加内存,避免出现宕机问题。

正文

Java进程 OOM的多种情况


摘要

OOM 其实有多种:

第一类是JVM原生自发处理的, 这种也分为多种情况. 
1. 堆区使用了比较多,并且大部分对象都还有引用, GC不出来可用内存, 
这是要给对象申请较大的内存空间时就会出现OOM的报错. 
2. 除了IP 下一条命令指针的内存的区域, 其他任何区域都存在OOM的风险. 
比如metadata,codecache,以及栈空间, 当然metadata一般时无限制的. 
栈空间一般是stack over flow的提示信息. 

第二类 操作系统进行的处理. 
当系统的内存使用较高的时候, 剩余空间几乎没有
此时如果有JAVA本服务的线程,或者是其他进程要跟操作系统申请内存使用. 
操作系统发现内存已经不足以支撑, 就会选择oom_score 得分比较高的进程进行kill
如果正好关闭了swap, 不会进行swapout/swapin的操作, 系统可能使用的很流畅.
突然就会宕机. 这种通过分析JVM是较难进行处理的. 

问题现象

今天下午现场一台机器突然宕机连不上. 
运维同事立即进行了服务启动. 
晚上时有人反馈系统出现宕机影响使用.
这边进行了一下简单的分析. 结果其实都是摘要里面的.
但是想把过程简单描述一下, 以便备忘. 

分析过程

方法很简单通过如下命令就可以
cat /var/log/messages |grep out_of_memory+  -C 20

其实我这边还可以通过
dmesg -T |grep -i oom 进行查看
但是发现不如上面一个命令系统详实. 

配合 系统的日志就可以进行分析. 

系统日志信息

Mar 15 14:58:52 localhost kernel: OkHttp Connecti invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0
Mar 15 14:58:52 localhost kernel: OkHttp Connecti cpuset=/ mems_allowed=0
Mar 15 14:58:52 localhost kernel: CPU: 4 PID: 23890 Comm: OkHttp Connecti Kdump: loaded Not tainted 3.10.0-1127.el7.x86_64 #1
Mar 15 14:58:52 localhost kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 12/12/2018
Mar 15 14:58:52 localhost kernel: Call Trace:
.................................
Mar 15 14:58:52 localhost kernel: Out of memory: Kill process 25813 (java) score 757 or sacrifice child
Mar 15 14:58:52 localhost kernel: Killed process 23697 (sh), UID 0, total-vm:113284kB, anon-rss:184kB, file-rss:0kB, shmem-rss:0kB
Mar 15 14:58:52 localhost kernel: Spring session  invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0
Mar 15 14:58:52 localhost kernel: Spring session  cpuset=/ mems_allowed=0
Mar 15 14:58:52 localhost kernel: CPU: 6 PID: 15972 Comm: Spring session  Kdump: loaded Not tainted 3.10.0-1127.el7.x86_64 #1
Mar 15 14:58:52 localhost kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 12/12/2018
Mar 15 14:58:52 localhost kernel: Call Trace:
Mar 15 14:58:52 localhost kernel: Call Trace:
Mar 15 14:58:52 localhost kernel: [<ffffffffaf97ff85>] dump_stack+0x19/0x1b
Mar 15 14:58:52 localhost kernel: [<ffffffffaf97a8a3>] dump_header+0x90/0x229
Mar 15 14:58:52 localhost kernel: [<ffffffffaf306ce2>] ? ktime_get_ts64+0x52/0xf0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3c246e>] oom_kill_process+0x25e/0x3f0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf333a41>] ? cpuset_mems_allowed_intersects+0x21/0x30
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3c1ecd>] ? oom_unkillable_task+0xcd/0x120
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3c1f76>] ? find_lock_task_mm+0x56/0xc0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3c2cc6>] out_of_memory+0x4b6/0x4f0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf97b3c0>] __alloc_pages_slowpath+0x5db/0x729
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3c9146>] __alloc_pages_nodemask+0x436/0x450
Mar 15 14:58:52 localhost kernel: [<ffffffffaf418e18>] alloc_pages_current+0x98/0x110
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3be377>] __page_cache_alloc+0x97/0xb0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3c0f30>] filemap_fault+0x270/0x420
Mar 15 14:58:52 localhost kernel: [<ffffffffc037da4e>] __xfs_filemap_fault+0x7e/0x1d0 [xfs]
Mar 15 14:58:52 localhost kernel: [<ffffffffc037dc4c>] xfs_filemap_fault+0x2c/0x30 [xfs]
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3edeea>] __do_fault.isra.61+0x8a/0x100
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3ee49c>] do_read_fault.isra.63+0x4c/0x1b0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf3f5d00>] handle_mm_fault+0xa20/0xfb0
Mar 15 14:58:52 localhost kernel: [<ffffffffaf98d653>] __do_page_fault+0x213/0x500
Mar 15 14:58:52 localhost kernel: [<ffffffffaf98d975>] do_page_fault+0x35/0x90
Mar 15 14:58:52 localhost kernel: [<ffffffffaf989778>] page_fault+0x28/0x30

进程信息

可以看到 上面一个被kill的信息为:
Out of memory: Kill process 25813
查看系统宕机之前的日志就可以确定是否是本进程
2023-03-15 14:47:56,845 localhost.localdomain ERROR [25813.85ec182.314.1]
 [Schd] org.hibernate.engine.jdbc.spi.SqlExceptionHelper

看到 ERROR 后面的第一个就是进程信息,致辞确认是被linux系统给kill了. 

问题原因分析与对策

1. GC日志里面没有任何Full GC多次出现的现象.
宕机之前系统运行是非常稳定的. 
2. 之前系统多次出现过swap分区使用过多的情况.导致卡顿.
为了避免过于卡顿影响业务,已经将swap分区关闭. 
3. dmesg 发现系统经常有OOM的情况. 

所以分析下来,在不特备影响系统性能的情况下只有两种解决策略: 
1. 适当降低jvm的堆区, 也就是降低 -Xms和-Xmx 给其他使用者空闲出来一部分资源.
2. 提高资源配置. 加大内存, 避免出现宕机的问题. 

问题的延伸思考

1. 一个机器. 可以分配多少内存给JVM的堆区? 
2. 内存应该如何分配,堆区,栈区,方法区,元数据区,本地内存等的配置. 以及留出部分内存给想系统和文件缓存使用.
3. docker 容器模式下. 如果使用ramMaxPercentage 的模式进行设置. 

堆区太小肯定性能不好, 太大了之后FullGC的STW时间需要控制. 
之前对功能还有自动化的环境进行过 NMT的内存跟踪, 堆区,一般占用总Java进程的75左右的内存. 
所以理论上 排除到系统必须的内存和一定的文件缓存之后. 堆区应该不能占用超过七成的可用内存 
避免出现宕机的情况. 

与Java进程 OOM的多种情况相似的内容:

Java进程 OOM的多种情况

Java进程 OOM的多种情况 摘要 OOM 其实有多种: 第一类是JVM原生自发处理的, 这种也分为多种情况. 1. 堆区使用了比较多,并且大部分对象都还有引用, GC不出来可用内存, 这是要给对象申请较大的内存空间时就会出现OOM的报错. 2. 除了IP 下一条命令指针的内存的区域, 其他任何区

[转帖]一次 Java 进程 OOM 的排查分析(glibc 篇)

https://juejin.cn/post/6854573220733911048 遇到了一个 glibc 导致的内存回收问题,查找原因和实验的的过程是比较有意思的,主要会涉及到下面这些: Linux 中典型的大量 64M 内存区域问题 glibc 的内存分配器 ptmalloc2 的底层原理 如

[转帖]一次 Java 进程 OOM 的排查分析(glibc 篇)

https://juejin.cn/post/6854573220733911048 遇到了一个 glibc 导致的内存回收问题,查找原因和实验的的过程是比较有意思的,主要会涉及到下面这些: Linux 中典型的大量 64M 内存区域问题 glibc 的内存分配器 ptmalloc2 的底层原理 如

[转帖][问题已处理]-kubernetes中2次不同的oom处理

https://dandelioncloud.cn/article/details/1598699030236577793 起因: 同事反馈 服务挂了,kuboard上查看是服务挂掉了,liveness port 异常,通过查看pod状态,发现服务被重启了。 1 pod里的java进程因为k8s主机

[转帖]某游戏海外版本堆外内存泄露排查

https://www.jianshu.com/p/cae00d9c99fe 某游戏海外版本堆外内存泄露排查 现象 线上有部分服务器用top发现Java进程内存占用占比达到99,而且出现了有一个服务器被Linux OOM Kill 排查 选择了110服,该机器的Java进程最大堆内存设置的是9710

[转帖]【JVM】Java内存区域与OOM

引入 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。 Java虚拟机运行时数据区 如图所示 1.程序计数器(线程私有) 作用 记录当前线程所执行到的字节码的行号。字节码解释器工作的时候就是通过改变这个计数器的值来选取下一条需要执行的字节

[转帖]【JVM】Java内存区域与OOM

引入 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。 Java虚拟机运行时数据区 如图所示 1.程序计数器(线程私有) 作用 记录当前线程所执行到的字节码的行号。字节码解释器工作的时候就是通过改变这个计数器的值来选取下一条需要执行的字节

[转帖]linux查看java堆栈信息_linux进程堆栈大小

https://www.cnblogs.com/cloudHui/p/17076184.html 1、查看JAVA进程JVM参数 jinfo -flags pid(进程号)-XX:CICompilerCount=2 最大的并行编译数-XX:InitialHeapSize=16777216 JVM 的

[转帖]通过Shell脚本自动监控JAVA进程中线程cpu使用率

https://gitee.com/jialy/auto-monitor-java-process/tree/master 本文主要介绍在 show-busy-java-threads.sh 脚本的功能基础上,通过 process-cpu-monitor.sh 脚本实现Linux平台上Java进程或

【转帖】Java Full GC (Ergonomics) 的排查

文章目录 1. Full GC (Ergonomics)1.1 Java 进程一直进行 Full GC1.2 Full GC 的原因1.3 检查堆占用 2. 代码检查3. 解决方式 1. Full GC (Ergonomics) 1.1 Java 进程一直进行 Full GC 例行检查线上运行的 J