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

javaOOM该分析dump文件而不是看异常log日志原因

目录

  • OOM异常--intsmaze
  • 正确姿势dump文件分析--intsmaze
  • 正确的姿势--intsmaze
  • dump丢失打印--intsmaze
  • 哪些内存溢出会产生dump文件--intsmaze

应用程序出现OOM异常,你是否仍然通过看日志的方式去排查问题(该方式定位解决问题是大概率的巧合而已)?正确的排查方案是进行dump文件分析,你知道为什么吗?

OOM异常--intsmaze

首先说一下,本人在开发中遇到的OOM异常基本也是通过看log日志去定位的(很多OOM异常是因为出现死循环或者查询返回的数据量多大,没有分页等等,通过异常日志我们确实能很快定位,但这不是正确的姿势。),只是碰巧刚好日志打印的异常栈信息就是对应的代码问题。
很多博客也说了,定位OOM异常通过分析dump日志,因此深表疑惑,为什么明明看log日志就能解决的非要去分析dump日志,网上也没有检索到满意的答案,问了身边的很多开发,也仅仅说dump进行性能分析,log日志进行异常排查。在我几度深思中,突然开窍,特此写下原因。

OOM异常会导致程序宕机,进程结束。

正确姿势dump文件分析--intsmaze

请看大屏幕:

public class OOMDump {

    static class OOMIntsmaze {
        public byte[] placeholder = new byte[64 * 1024];
    }

    public static void fillHeap(ArrayList<OOMIntsmaze> list, int num) throws Exception {

        for (int i = 0; i < num; i++) {
            list.add(new OOMIntsmaze());
            System.out.println(i);
        }
    }

    public static void main(String[] args) throws Exception {
        ArrayList<OOMIntsmaze> list = new ArrayList<OOMIntsmaze>();
        fillHeap(list,131);
        Thread.sleep(20000000);
    }
}

我们配置jvm参数如下 -Xmx10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d://
当fillHeap(list,131)时,程序正常执行;当fillHeap(list,132)时,程序就会报OOM异常:

130
java.lang.OutOfMemoryError: Java heap space
Dumping heap to d://\java_pid10000.hprof ...
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at cn.intsmaze.dump.OOMDump$OOMIntsmaze.<init>(OOMDump.java:27)
    at cn.intsmaze.dump.OOMDump.fillHeap(OOMDump.java:34)
    at cn.intsmaze.dump.OOMDump.main(OOMDump.java:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
Heap dump file created [10195071 bytes in 0.017 secs]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

通过异常日志我们可以看到,是因为代码
at cn.intsmaze.dump.OOMDump.fillHeap(OOMDump.java:34)
list.add(new OOMIntsmaze());
导致的问题,通过日志所见即所得,我立马解决了问题,为什么要看dump日志呢?我有病啊。

其实不然,骚年。假如main方法如下,执行

    public static void main(String[] args) throws Exception {
        ArrayList<OOMIntsmaze> list = new ArrayList<OOMIntsmaze>();
        fillHeap(list,131);
        Map<String,OOMIntsmaze> map=new HashMap<String,OOMIntsmaze>();
        map.put("LIUYANG",new OOMIntsmaze());
        map.put("intsmaze",new OOMIntsmaze());
        Thread.sleep(20000000);
    }

这个时候我们通过异常日志发现是因为map.put("LIUYANG",new OOMIntsmaze());导致的,找到代码发现,map里面才插入了一条数据,没有出现死循环,怎么会导致OOM异常了,真是活久见了。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at cn.intsmaze.dump.OOMDump$OOMIntsmaze.<init>(OOMDump.java:27)
    at cn.intsmaze.dump.OOMDump.main(OOMDump.java:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

设置10M我们可以发现list添加132各个元素时会发生OOM,这个时候我们向list添加131个元素,然后执行map添加,发现map添加一个元素就报错。此时的oom异常日志定位的是map添加元素导致的。
但是真实情况不是的,因为看代码也会发现map只添加了2个元素,怎么会是他造成的。map的添加只是刚好此时jvm内存达到容量上限了。
所以要找到根本问题,是需要通过dump文件分析OOM时,各个对象的容量状态。
而且实际情况中,map.put()的代码并不会向上面示例一样和list.add()代码放在一块,而是位于不同的包下,不同的业务流程中。这个时候看log日志去定位基本不可能了。
但是为什么大家出行OOM异常还是通过看log日志而且定位的位置是正确的。只是因为向list.add这种循环中,一直在执行,基本大概率是他触发的。

正确的姿势--intsmaze

所以为了防患于未然,程序猿在开发的时候,一定要配置jvm启动参数HeapDumpOnOutOfMemoryError。
参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析
758427-20180828185246502-1691551912.png

dump丢失打印--intsmaze

有些时候,我们的应用程序宕机,既不会打印log日常信息,dump文件也不会生成,这个时候基本就是linux系统杀掉了我们的应用程序进程。

查看/var/log/messages文件

messages 日志是核心系统日志文件。它包含了系统启动时的引导消息,以及系统运行时的其他状态消息。在messages里会出现以下信息

out of memory:kill process 8398(java) score 699 or sacrifice child
killed process 8398,UID 505,(java) total-vm:2572232kB,anno-rss:1431292kB,file-rss:908kB

oom killer是linux系统的一个保护进程,当linux系统所剩的内存空间不足以满足系统正常运行时,会触发。oomkiller执行时,会找出系统所有线程的score值最高的那个pid,然后干掉。
这里我们可以看到,JAVA进程的确是被LINUX的oom killer干掉了。

我们的应用程序和日志都只能记录JVM内发生的内存溢出。如果JVM设置的堆大小超出了操作系统允许的内存大小,那么操作系统会直接杀死进程,这种情况JVM就无法记录本次操作。
Linux对于每个进程有一个OOM评分,这个评分在/proc/pid/oom_score文件中。例如/proc/8398/oom_score,如果不希望杀死这个进程,就将oom_adj内容改为-17。
更多关于linux的oom killer机制请自行百度检索。

最正确的姿势:首先调整JVM的heap大小,使得JVM的OOM优先于操作系统的OOM出现,接着设置运行参数,在发生OOM的时候输出heapdump文件。

哪些内存溢出会产生dump文件--intsmaze

请上公交车:JVM各种内存溢出是否产生dump https://blog.csdn.net/stevendbaguo/article/details/51366181

相关文章:

  • DNS 工作原理是什么,域名劫持、域名欺骗、域名污染又是什么
  • NOIP2011DAY1T3 Mayan游戏
  • 1109 Group Photo
  • 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定义筛选,Redis入门 11.1...
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 串口发送数据速度
  • Lsb图片隐写
  • react-native-echarts 在手机上 图表出现滚动条解决方法
  • Python利用Selenium自动登录掘金
  • ASP.NET CORE Combines Angular to Create SPA
  • 海量数据处理 - 十道面试题与十个海量数据处理方法总结
  • 如何搭建一个完整的交易框架
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • easyui datagrid 相关取数据总结
  • 平台化技术:从C/S到B/S
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • Apache Zeppelin在Apache Trafodion上的可视化
  • Babel配置的不完全指南
  • Django 博客开发教程 8 - 博客文章详情页
  • Flannel解读
  • iOS | NSProxy
  • React 快速上手 - 07 前端路由 react-router
  • RxJS: 简单入门
  • Sequelize 中文文档 v4 - Getting started - 入门
  • SOFAMosn配置模型
  • spring boot下thymeleaf全局静态变量配置
  • Spring声明式事务管理之一:五大属性分析
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 三栏布局总结
  • 详解NodeJs流之一
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​如何防止网络攻击?
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • #{} 和 ${}区别
  • #《AI中文版》V3 第 1 章 概述
  • #define,static,const,三种常量的区别
  • #pragma 指令
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (zt)最盛行的警世狂言(爆笑)
  • (办公)springboot配置aop处理请求.
  • (笔试题)合法字符串
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (九十四)函数和二维数组
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转)Oracle存储过程编写经验和优化措施
  • (转)Sublime Text3配置Lua运行环境
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • *** 2003
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .net framework 4.0中如何 输出 form 的name属性。