java OOM还在看log日志,兄弟你错的的很严重,正确方式是分析dump文件
应用程序出现OOM异常,你是否仍然通过看日志的方式去排查问题(该方式定位解决问题是大概率的巧合而已)?正确的排查方案是进行dump文件分析,你知道为什么吗?
OOM异常--intsmaze
首先说一下,本人在开发中遇到的OOM异常基本也是通过看log日志去定位的(很多OOM异常是因为出现死循环或者查询返回的数据量多大,没有分页等等,通过异常日志我们确实能很快定位,但这不是正确的姿势。),只是碰巧刚好日志打印的异常栈信息就是对应的代码问题。
很多博客也说了,定位OOM异常通过分析dump日志,因此深表疑惑,为什么明明看log日志就能解决的非要去分析dump日志,网上也没有检索到满意的答案,问了身边的很多开发,也仅仅说dump进行性能分析,log日志进行异常排查。在我几度深思中,突然开窍,特此写下原因。
正确姿势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出当前的内存堆转储快照以便事后进行分析
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
java OOM还在看log日志,兄弟你错的的很严重,正确方式是分析dump文件的更多相关文章
- Android开发华为手机无法看log日志解决方法
Android开发华为手机无法看log日志解决方法 上班的时候,由于开发工具由Eclipse改成Android Studio后,原本的华为手机突然无法查看崩溃日志了,大家都知道,若是无法查看日志要它毛 ...
- Android开发之华为手机无法看log日志解决方法(亲测可用华为荣耀6)
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, 转载请说明出处. 在上家公司上班的时候,公司配了华为荣耀6的测试机,发现在eclipse下 无法查看 ...
- [Java基础] 使用JMAP dump及分析dump文件
转载:http://blog.csdn.net/kevin_luan/article/details/8447896 http://liulinxia02.blog.163.com/blog/stat ...
- java程序显示log日志信息的方法
首先需要引入maven依赖 <dependency> <groupId>commons-logging</groupId> <artifactId>co ...
- Android学习笔记——log无法输出的解决方法和命令行查看log日志
本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblogs.com/JohnTsai/p/3983936.html. 知识 ...
- java内存dump文件导出与查看
生成dump文件的命令:jmap -dump:format=b,file=20170307.dump 16048file后面的是自定义的文件名,最后的数字是进程的pid 使用jvisualvm来分析d ...
- Java获取执行进程的dump文件及获取Java stack
转发自https://blog.csdn.net/MCC_MCC_MCC/article/details/80623156 1.Windows/Linux环境下查看Java进程ID方法 使用Java自 ...
- java中关于log日志
博:http://zhw2527.iteye.com/blog/1006302 http://zhw2527.iteye.com/blog/1099658 在项目开发中,记录错误日志是一个很有必要功能 ...
- java中log日志的使用(完全版)
Commons_logging包 Apache通用日志包 他为Log4JLogger:NoOpLog:LogKitLogger:Jdk14Logger:AvalonLogger提供了一共通用的接口进行 ...
随机推荐
- 闭包,jQuery插件的写法:图片预加载
最近做的一些网页,单个网页图片量都比较大,网络不好的情况下,特别卡,这个图片预加载的方法可以牺牲一些时间换来网页的浏览顺畅,还是值得的. //闭包的写法,它内部的变量都是局部的,不会和外部巳有的变量进 ...
- mac 下 ipython+notebook
python做数据分析相关的工具的安装和配置,以及numpy的入门 为什么要用PYTHON来做数据分析 MATLAB R语言,语法类似C语言,但是它在语义上是函数设计语言,也是开源的. python ...
- AIOps 平台的误解,挑战及建议(中)— AIOps常见的误解
本文篇幅较长,分为上,中,下,三个部分进行连载.内容分别为:AIOps 背景/所应具备技术能力分析(上),AIOps 常见的误解(中),挑战及建议(下). 前言 我大概是 5,6 年前开始接触 ITO ...
- Hive分区
注意:必须在表定义时指定对应的partition字段. 一.指定分区 1.单分区 建表语句:create table day_table(id int, content string) partiti ...
- Spark操作HBase报:org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException异常解决方案
一.异常信息 19/03/21 15:01:52 WARN scheduler.TaskSetManager: Lost task 4.0 in stage 21.0 (TID 14640, hnte ...
- Multiple Server Query Execution报The result set could not be merged..
在SQL Server中使用Multiple Server Query Execution这个功能做数据库维护或脚本发布时非常方便,昨天由于磁盘空间原因,删除清理了大量的软件和组件,结果导致SSMS客 ...
- Linux修改挂载目录名称
Local系统管理员新增了一个VG,将一个原挂载点/u02改为了/u02-old, 如下所示. [root@mylnx01 ~]# df -h Filesystem Size ...
- 智能合约 solidity 开发的环境基本搭建
以太坊Dapp开发快速入门 以太坊为开源社区,虽然设计东西都很优秀,但是组件十分的杂乱,因此下面首先简单介绍下以太坊的一些常用组件以及各种工具介绍 Geth Geth是由以太坊基金会提供的官方客户端软 ...
- 如何设置可以避免php代码中的中文在浏览器中成为乱码?
其实很简单,只需要在代码开始的前面加上一条这样的语句就行: //这里面我的浏览器中的字符编码格式为utf-8,所以这里我设置为utf-8,如果你的浏览器中的默认编码不是这个,请选择浏览器默认的编码格式 ...
- spring cloud 实践之hystrix注意事项
当我们写类似下面代码时 package demo1.demo1; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org ...