目录
参考链接
1、名词解释
内存泄露:代码中的某个对象本应该被虚拟机回收,但是因为GCRoot引用而没有被回收。
内存溢出:虚拟机由于堆中拥有太多不可回收对象没有回收,导致无法继续创建新对象。
2、常见异常
java堆内存异常
java.lang.OutOfMemoryError: Java heap space
原因:异常导致-Xms或-Xmx配置不足。(注意,-Xmx 堆内存的最大大小,默认为物理内存的1/4,-Xms 堆内存的初始大小,默认为物理内存的1/64,-Xmn 堆内新生代的大小。通过这个值也可以得到老生代的大小:-Xmx 减去 -Xmn。
- 使用了大量的递归或无限递归对象。
- 使用了大量循环或死循环(循环中用到了大量的新建的对象)。
- 使用了向数据库查询过多,可能会造成内存溢出。
- 有数组,List,Map中存放的是对象的引用而不是对象,这些引用会让对应的对象不能被释放。会大量存储在内存中。
java栈内存异常
Exception in thread "main" java.lang.StackOverflowError
原因:对象过大或过多异常,导致-Xss配置的内存不足。(注意,设置每个线程可使用的内存大小,即栈的大小。大小设置需要注意,太小了容易栈溢出,太大了影响创建栈的数量。双刃剑,看把握。
- 是否有递归调用。
- 是否有大量循环或死循环。
- 全局变量是否过多。
- 数组、List、map数据是否过大。
方法区内存异常
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
原因:异常导致-XX:MetaspaceSize或-XX:MaxMetaspaceSize配置不足。
3、解决思路
》通过日志文件,定位异常代码位置,分析问题原因。
》当不通过日志文件主观来判断出问题代码时,通过dump文件来分析。
》上 Arthas 工具。
4、生成dump文件的三种方式
jvisualvm
说明:jvisualvm 控制台,监控时主动生成dump文件。
-
有界面,可以指定发生 OOM 时生成 dump,可以用 everything 工具搜索保存的路径,文件名称为 java_pidxxxx.hprof。
-
jvisualvm.exe 工具在本地 java 的 jdk 安装路径,一般在 bin 目录里,如:D:\dev\java\jdk1.8.0_172\bin\jvisualvm.exe
-
可以实时监控 cpu、内存、类、线程等的运行情况。
-
生成的 *.hprof 文件,可以使用 MAT工具进行分析,全称:Memory Analyzer。
jmap命令
说明:使用jmap命令生成dump文件
windows环境:
jmap -dump:live,format=b,file=heap.hprof <pid> // tasklist | grep xxx
linux环境:
jmap -dump:live,format=b,file=heap.hprof <pid> // ps -elf | grep xxx
[zoms@ocs ~]$ jmap -dump:live,format=b,file=heap-vm.hprof 15463
Dumping heap to /home/zoms/heap-vm.hprof ...
Heap dump file created
应用启动配置
说明:在应用启动时配置添加 -XX:+HeapDumpOnOutOfMemoryError 参数。此时如果应用抛出 OutOfMemoryError 时,会自动生成 dump 文件。
目录指定:XX:HeapDumpPath。(不指定则在对应工程目录下面,找 java_pidxxxx.hprof 文件)
注:如果打开 Edit Configuration 里面,没有 VM options 的选项,可以点击 Modify options,将其添加上。
举例:
1、设置上下限分别是20,40
-Xms20m -Xmx40m -XX:+HeapDumpOnOutOfMemoryError
2、运行测试代码,生成dump文件。
3、使用MAT打开,并进行分析。
5、Memory Analyzer 分析工具
1、基础步骤:
》打开软件,File-Open Heap Dump,在开始向导中勾选第一个(Leak Suspects Report).
》Overview,内存的整体情况。
》点击下面的Reports-Leak Suspects,生成报告,查看导致内存泄露的罪魁祸首。
》根据饼图以及下方的报告说明,来分析内存泄露的具体原因。
》点击报告中Details链接,可以看到更加详细的列表说明项,其中:
Shallow Heap:为对象自身占用的内存大小,不包括它引用的对象。
Retained Heap:为当前对象大小 + 当前对象可直接或间接引用到的对象的大小总和。
2、Overview页面的常用的Actions:
Histogram:查看每个类的对象实例的个数。
详情页功能:
1)对象的引用与被引用 : 右键点击某对象 , 选择 List objects 选项 ;
》查看该对象引用了哪些对象 : 选择 with incoming reference 选项 ;
》查看该对象被哪些对象引用 : 选择 with outgoing reference 选项 ;
2)查看对象到GC Roots的最短距离:
在右键菜单中选择 " Merge Shortest Paths to GC Roots " , 这里就可以看到为什么对象可达性分析时 , 某些对象应该释放 , 却仍然存在与 GC Root 对象之间的引用链 ;
GC Roots 与 GC 垃圾回收:存在与 GC Roots 引用链导致内存泄漏 : 该对象可能与 GC Root 对象不是直接引用 , 而是由其它对象简介引用 , 导致存在这么一条引用链 ;
在查询到GC root的路径时,默认是包含所有引用的,从GC角度说,一个对象无法被GC,一定是因为有强引用存在,其它引用类型在GC需要的情况下都是可以被GC掉的,所以这里我们一般使用 exclude all phantom/weak/soft etc. references,即只查看GC路径上的强引用。
上图标识了从当前对象到GC roots的路径,这个路径解释了为什么当前对象还能存活,对分析内存泄露很有帮助。
标签:java,dump,对象,GC,内存,工具,引用 From: https://www.cnblogs.com/selonsy/p/17573370.html