当前位置: 首页 > news >正文

oom java问题_Java OOM问题如何排查

@

OOM 问题

什么是OOM

OOM为out of memory的简称,来源于java.lang.OutOfMemoryError,指程序需要的内存空间大于系统分配的内存空间,OOM后果就是程序crash;可以通俗理解:程序申请内存过大,虚拟机无法满足,然后自杀了。

导致OOM问题的原因

为什么会没有内存了呢?原因不外乎有两点:

1)分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。

2)应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。

内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。

内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。

最常见的OOM情况有以下三种:

java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。

java.lang.OutOfMemoryError: PermGen space 或 java.lang.OutOfMemoryError:MetaSpace ------>java方法区,(java8 元空间)溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。

java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

排查手段

一般手段是:先通过内存映像工具对Dump出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏还是内存溢出。

如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。这样就能够找到泄漏的对象是通过怎么样的路径与GC Roots相关联的导致垃圾回收机制无法将其回收。掌握了泄漏对象的类信息和GC Roots引用链的信息,就可以比较准确地定位泄漏代码的位置。

如果不存在泄漏,那么就是内存中的对象确实必须存活着,那么此时就需要通过虚拟机的堆参数( -Xmx和-Xms)来适当调大参数;从代码上检查是否存在某些对象存活时间过长、持有时间过长的情况,尝试减少运行时内存的消耗。

实战

接下来用一个简单的案例,展示OOM问题排查过程

public class OomDemo {

public static void main(String[] args) {

StringBuilder stringBuilder = new StringBuilder();

while(true){

stringBuilder.append(System.currentTimeMillis());

}

}

}

执行代码时,通过设置JVM参数达到OOM的目的

java -Xmx10m -Xms10m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=oom.hprof OomDemo

-XX:+HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath参数分别用于指定发生OOM是否要导出堆以及导出堆的文件路径

这个方法也可以通过jmap实时生成

jmap -dump:format=b,file=$java_pid.hprof #java_pid为java进程ID

以上命令执行后,程序会出现如下错误:

java.lang.OutOfMemoryError: Java heap space

Dumping heap to oom.out ...

Heap dump file created [3196858 bytes in 0.016 secs]

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at java.util.Arrays.copyOf(Arrays.java:3332)

at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)

at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:700)

at java.lang.StringBuilder.append(StringBuilder.java:214)

at jvm.OomDemo.main(OomDemo.java:13)

MAT分析

首先使用MAT打开刚刚导出的hprof文件,选择报告里的泄露嫌疑分析 Leak Suspects Report

cb6693a5dcc59829af186fd02ac5d052.png

可以看到有一个本地变量,站了总存储的92%,实际占用的是char[],See stacktrace,可看到该对象所在线程的堆栈信息:

2ebf118d844ee3fe2768fb1f0250bd6c.png

通过这儿,可以定位到发生OOM的代码段,至此,可根据具体代码具体分析。

44d3f8e5c5b4a4a20c4757f51aa33b1a.png

相关文章:

  • java 视图对象_java – 从不同资源创建视图对象的最佳方法(模式?)
  • java where函数_CONSTRUCT / WHERE中的SPARQL函数
  • mysql上机考试_SQL上机试题及步骤
  • 2d unity 多物体 射线_Unity 2D射线与 3D射线 UI射线
  • java数据如何显示在HTML界面_ajax接收后台数据在html页面显示
  • java mqtt broker_mqtt broker集合
  • notes 发邮件was配置java_Java程序调用LotusNotes邮件服务发送邮件的实现
  • java this 逸出_this引用逸出
  • java单机多核怎么实现的_JAVA实现对于多核CPU的OS满足CPU使用率在50%左右以及实现CPU使用率为正弦曲线-Go语言中文社区...
  • java序列化第二次出错_1.2.28反序列化类bug java.lang.VerifyError:
  • java对mysql读写权限设置_Mac 配置java版本 ---- MySql数据库权限设置 --- openfire
  • java中英对比_中英文代码对比系列之Java一例
  • java 算术字符串_java-从定义为字符串的运算符执行算术运算
  • c#项目 java项目_c#项目转Java项目!!!!!
  • mysql 创建xml字段_用MySQL和PHP创建XML
  • 【知识碎片】第三方登录弹窗效果
  • Android优雅地处理按钮重复点击
  • Angular 4.x 动态创建组件
  • Javascript弹出层-初探
  • MySQL的数据类型
  • python 学习笔记 - Queue Pipes,进程间通讯
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • React系列之 Redux 架构模式
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • Vue学习第二天
  • XML已死 ?
  • 笨办法学C 练习34:动态数组
  • 将回调地狱按在地上摩擦的Promise
  • 开源SQL-on-Hadoop系统一览
  • 那些被忽略的 JavaScript 数组方法细节
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • ​ubuntu下安装kvm虚拟机
  • !$boo在php中什么意思,php前戏
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #Linux(Source Insight安装及工程建立)
  • (39)STM32——FLASH闪存
  • (C++17) std算法之执行策略 execution
  • (动态规划)5. 最长回文子串 java解决
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (一)基于IDEA的JAVA基础12
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .net 7 上传文件踩坑
  • .NET 8.0 发布到 IIS
  • .NET 中 GetProcess 相关方法的性能
  • .netcore 获取appsettings
  • .net和php怎么连接,php和apache之间如何连接
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • @Autowired标签与 @Resource标签 的区别
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [CDOJ 838]母仪天下 【线段树手速练习 15分钟内敲完算合格】
  • [docker] Docker的私有仓库部署——Harbor
  • [hdu 3746] Cyclic Nacklace [kmp]