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的多种情况的更多相关文章

  1. 通过JDK常用工具监控Java进程的内存占用情况

    目录 1 JDK 工具的使用 2 查看 GC 日志信息 3 添加 JMS 远程监控 Tomcat是一款常用的Web容器, 它是运行在 JVM(Java Virtual Machine) 中的一个Jav ...

  2. linux 查看Java 进程的内存使用情况

    top -b -n 1 | grep java| awk '{print "PID:"$1",mem:"$6",CPU percent:"$ ...

  3. 性能分析(1)- Java 进程导致 CPU 使用率升高,问题怎么定位?

    性能分析小案例系列,可以通过下面链接查看哦 ps:这些分析小案例不能保证百分比正确,是博主学习过程中的总结,仅做参考 前提 本机有一个很占用 CPU 的项目,放在了 Tomcat 下启动着 如何定位 ...

  4. java进程被OOM干掉问题记录

    异常现象:用户环境部署了一台iserver,访问一阵后,进程没了   分析: 1.bin目录下没有崩溃日志,在tomcat的访问日志里面也没有看到有用的信息.iserver.log里面也没有信息 2. ...

  5. 【20180129】java进程经常OOM,扩容swap。

    导读:线上一台服务器专门做为公司内部apk打包服务,由于app的业务和功能与时俱增,apk打包需要依赖的资源越来越多,最近这几天每次apk打包的时候都会由于OOM导致打包失败.由于apk打包业务并不是 ...

  6. Java进程&线程(整理)

    Java进程&线程 程序:程序员写的代码,就是代码,不运行好像不会发生什么: 进程:一个进程可以理解为"运行的"一个程序,当我们启动一个java程序后,对应的jvm就会创建 ...

  7. Java进程&线程(一)

    Java进程&线程 程序:程序员写的代码,就是代码,不运行好像不会发生什么: 进程:一个进程可以理解为"运行的"一个程序,当我们启动一个java程序后,对应的jvm就会创建 ...

  8. JVM源码分析之一个Java进程究竟能创建多少线程

    JVM源码分析之一个Java进程究竟能创建多少线程 原创: 寒泉子 你假笨 2016-12-06 概述 虽然这篇文章的标题打着JVM源码分析的旗号,不过本文不仅仅从JVM源码角度来分析,更多的来自于L ...

  9. 分析java进程假死状况

    摘自: http://www.myexception.cn/internet/2044496.html 分析java进程假死情况 1 引言 1.1 编写目的 为了方便大家以后发现进程假死的时候能够正常 ...

  10. 如何优雅地停止Java进程

    目录 理解停止Java进程的本质 应该如何正确地停止Java进程 如何注册关闭钩子 使用关闭钩子的注意事项 信号量机制 总结 理解停止Java进程的本质 我们知道,Java程序的运行需要一个运行时环境 ...

随机推荐

  1. 简化业务代码开发:看Lambda表达式如何将代码封装为数据

    摘要:在云服务业务开发中,善于使用代码新特性,往往能让开发效率大大提升,这里简单介绍下lambad表达式及函数式接口特性. 1.Lambda 表达式 Lambda表达式也被称为箭头函数.匿名函数.闭包 ...

  2. Java程序员都要懂得知识点:原始数据类型

    摘要:Java原始数据类型有short.byte.int.long.boolean.char.float.double.原始数据是未处理的或简化的数据,它构成了物理存在的数据,原始数据具有多种存在形式 ...

  3. IIS 设置超时时间

    高级设置 => 限制 => 连接超时(秒),默认120秒,根据实际情况调整

  4. PPT 动画-滚动数字

    插入一个文本框,输入 0~9 调整边框大小,使其竖着排列 页面切换,选择平滑

  5. pytest+request+allure生成测试报告

    基本流程 模拟数据 url,paras,method,except http://www.baidu.com, {k=12}, get, 200 请求url (接口文档) 参数 请求方法 预期返回响应 ...

  6. protobuf安装、编译和使用

    protobuf使用简单示例 一.安装 首先下载protobuf的安装包,我这里使用的是protobuf-cpp-3.21.5.tar.gz 解压安装包 tar -xzf protobuf-cpp-3 ...

  7. Educational Codeforces Round 104 (Rated for Div. 2) A-E 个人题解

    比赛链接 1487A. Arena n 个 Hero,分别有 \(a_i\) 的初始等级.每次两个 Hero 战斗时:等级相同无影响,否则等级高的英雄等级+1.直到某个英雄等级到了 \(100^{50 ...

  8. SpringBoot 动态数据源

    SpringBoot 实现动态数据源切换 Spring Boot + Mybatis Plus + Druid + MySQL 实现动态数据源切换及动态 SQL 语句执行. 项目默认加载 applic ...

  9. zookeeper源码(03)启动流程

    本文将从启动类开始详细分析zookeeper的启动流程: 加载配置的过程 集群启动过程 单机版启动过程 启动类 org.apache.zookeeper.server.quorum.QuorumPee ...

  10. 【C/C++】宏参数多对一和宏部分替换

    宏参数多对一:使用分号分隔多参数 宏部分替换:替换需要转换的再与后续宏接续 #include <stdio.h> #define _MESS_FAILED() printf("% ...