博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA 内存溢出 分析
阅读量:4078 次
发布时间:2019-05-25

本文共 2707 字,大约阅读时间需要 9 分钟。

需要用到的工具:

1.eclips 

2.MemoryAnalyzer    http://mirror.downloadvn.com/eclipse//mat/1.6.1/rcp/MemoryAnalyzer-1.6.1.20161125-win32.win32.x86_64.zip

代码如下:

package cn.sigangjun.memoryManage;import java.util.*;/* * 测试内存溢出 * VM args: -Xms20m -Xmx20M -XX:+HeapDumpOnOutOfMemoryError */public class HeapOOM {	int num;	public HeapOOM() {		num = 100000;		// TODO Auto-generated constructor stub	}	public static void main(String[] args) {		Object object = System.getProperties().get("os.name");				System.out.println(object);		List
list = new ArrayList
(); while (true) list.add(new HeapOOM()); }}

运行出错,错误信息如下:

Windows 7java.lang.OutOfMemoryError: Java heap spaceDumping heap to java_pid9296.hprof ...Heap dump file created [31216829 bytes in 0.082 secs]

找到java_pid9296.hprof .文件(位于项目的的根目录)

使用MemoryAnalyzer  工具打开,具体步骤如下:

以下为引用:  http://blog.csdn.net/mhmyqn/article/details/48054219

在项目运行过程中,可能会出现内存溢出,内存溢出的原因多种多样,而在内存溢出后,我们如何查找和分析内存溢出的原因呢?这里来说一说我遇到的次遇到的内存溢出经历。

大致情况是这样的:应用在启动后,过一段时间(这个时间不确定),内存忽然爆满,然后频繁的YGC,一会过后,老年代爆满,然后是频繁的FGC,最终撑爆内存,抛出OOM。重启应用后,还是这个过程。

1、查看java进程的内存使用情况和GC情况

通过jastat工具查看GC情况,以及各generation占用比例:

[plain]   
  1. jstat -gcutil <pid> 1000  

通过观察分析是否是JVM的运行内存分配不合理,可通过新生代、老年代内存占用情况,以及GC情况观察得出。

如果FGC很频繁,说明老年代被迅速占用满,这有可能是老年代本身分配的内存太小,或者是内存中大量对象被引用,导致无法被YGC等等,最终这些对象都进入老年代导致老年代爆满。

要分析是什么原因造成的,可以获取内存溢出时JVM的内存快照,通过对快照的分析,来定位内存溢出的原因。

通过jmap查看JVM堆内存概况:

[plain]   
  1. jmap -heap <pid>  

这个内存概况会根据使用的垃圾收集器的不同而有所差异。

2、获取jvmdump

获取jvmdump可通过添加应用服务器(如tomcat)启动参数:

[plain]   
  1. -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/mikan/jvmdump  

配置该参数后,在内存溢出时,JVM就会自动dump出当时的内存快照到HeapDumpPath指定的目录。

也可通过jmap在线获取内存dump,只是在使用jmap获取dump期间应用会被卡住,这可能对线上应用会有影响。如

[plain]   
  1. jmap -J-d64 -dump:format=b,file=/home/mumq/jvmdump.hprof <pid>  

其中pid为进程的ID。

获取到JVM内存快照后,可以使用相关的工具来对它进行分析。

3、分析jvmdump

jvmdump文件一般比较大(几个G),所以在做离线分析时,千万别在服务器上,因为在解析jvmdump时,会占用极大的内存,如果在服务器上,很可能影响线上应用的正常运行。所以一般情况是down到空闲的机器上做离线分析。

分析jvmdump的工具有很多,这里推荐使用的是Memory Analyzer (MAT),下载地址是:

当前最新Release版本是1.4.0,提供了两种版本:eclipse插件和独立版本,都可通过上面链接下载。

这里以独立版本为例。在开始分析dump文件之前,先设置MAT的内存,可根据分析的dump文件大小来设置,如果分析的dump文件为2G,那设置2G内存的话,那么解析dump文件生成report会很快,否则,等几个小时都不知道。。

如何设置?在与MAT相同目录下的MemoryAnalyzer.ini文件中添加如下配置:

[plain]   
  1. -vmargs  
  2. -Xms2048m  
  3. -Xmx4096m  

具体MAT的使用方法,可以直接查看MAT自带的示例教程,相对来说还是比较全面的。

在MAT解析完内存快照后,会生成相应的report,通过report可以看到当时内存使用情况、内存溢出的可疑之处(Leak Suspects)。如:

点击Leak Suspects,可以查看到具体的详细信息:

点击detail,查看详细信息,通过 Accumulated Objects by Class in Dominator Tree列表可以看到:

User对象有10W+,怎么会这样呢?通过 Accumulated Objects in Dominator Tree列表可以看到:

是调用了UserServiceImpl.login方法,一次性查询出了10W+的用户数据。如果频繁的调用该方法,则会很快的导致OOM。再查看代码发现在调用login方法时,如果用户名参数传null时,会查询出所有用户名为null的用户。这在数据量还很小或者请求量不大的时候,可能不会有什么问题,一旦数据量上来了,或请求量上来了,那很快就会出现OOM。

找到问题原因,如何解决就容易了。所以在写代码的时候如果考虑不周全,就有可能导致这种OOM的bug。

血的教训啊。

你可能感兴趣的文章
我感觉很有必要多刷刷leetcode
查看>>
关于单链表排序,倒置的具体方法(华清的方法,比我的好些)
查看>>
C语言计算数组长度时注意事项
查看>>
Vi复制一整行和复制多行
查看>>
快速排序qsort函数的compar参数
查看>>
应该至少掌握一门高级语言JAVA或C++
查看>>
我觉得你学编程或者找工作也可以用考研数学这种思想,做一百张卷子。
查看>>
选取的学习资料越难,学习效率越高。
查看>>
结构体嵌套结构体
查看>>
标准IO与文件IO的区别
查看>>
输出错误信息时,你不写课本上那样的if判断是否出错好像也是可以的
查看>>
就去把一本书啃烂
查看>>
linux API种类
查看>>
Linux系统编程之管理目录与文件的stat函数组
查看>>
目录流
查看>>
文件流、目录流、文件描述符总结
查看>>
Linux应用开发自学之路(转载)
查看>>
找工作准备的方向(4月22日写的)
查看>>
关于fwrite写入文件后打开查看是乱码的问题
查看>>
用结构体指针前必须要用malloc,不然会出现段错误
查看>>