Java的dump文件分析及JProfiler使用
Java的dump文件分析及JProfiler使用
1 dump文件介绍
从软件开发的角度上,dump文件就是当程序产生异常时,用来记录当时的程序状态信息(例如堆栈的状态),用于程序开发定位问题。
idea配置发生OOM的时候指定路径生成dump文件
# 指定发生OOM异常的时候,在d盘下生成对应的dump文件-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\
2 JProfiler介绍
2.1 下载
JProfiler下载:
链接:https://pan.baidu.com/s/1WXCc4FMOC3QQtjkhY4Qeow
提取码:5xrm
版本:JProfiler 12.0.4
2.2 与idea集成
-
本地windows下载并安装好JProfiler
-
idea安装JProfiler插件
-
指定本地windows的JProfiler路径[settings - tools]
4. 点击图标启动,JProfiler就默认监控到了指定Java程序
2.3 基本使用
①JProfiler基本参数
在概览页我们可以清晰的看到内存使用量、垃圾收集活动、类加载数量、线程个数和状态、CPU 使用率等指标随时间变化的趋势。
通过此图,我们可以作出如下基本判断:
- 程序在运行过程中会产生大量对象,但这些对象生命周期极短,大部分都能被垃圾收集器及时回收,不会造成内存无限增长。
- 加载类的数量在程序初始时增长较快,随后保持平稳,符合预期。
- 在程序运行过程中,有大量线程处于阻塞状态,需要重点关注。
- 在程序刚启动时,CPU 使用率较高,需要进一步探究其原因。
②测试分析dump文件
- 模拟OOM
public class JProfilerTest { public static void main(String[] args) throws InterruptedException { List<byte[]> list = new ArrayList<>(); while (true) { byte[] bytes = new byte[1024 * 1024 * 50]; list.add(bytes); TimeUnit.SECONDS.sleep(1); } }}
- 程序添加VM Options
# 监控OOM,发生OOM之后指定dump文件生成到d:\-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\
- JProfiler方式启动程序,观察控制台打印
程序运行一段时间之后,发生OOM异常
5. 查看dump文件,用JProfiler打开
6. 分析dump文件
查看最大对象内部结构
可以发现是改list中含有了太多的byte[]数组
ps:
其他查看方法类似
3 常见JVM问题
3.1 OOM
①堆溢出
原因:
1. 无法在Java堆中分配对象2. 应用程序保存了无法被GC回收的对象3. 程序过度使用finalizer
排查思路:
- 查看关键报错信息
- 使用内存映像分析工具(MAT或JProfiler)分析dump文件,分析是内存泄漏还是内存溢出
- 如果是内存泄漏,通过工具查看泄漏对象到GC Roots引用链,修复内存泄漏
- 如果不是,检查代码是否有死循环,递归等,再考虑用
-Xmx增加堆大小
demo代码JVM配置参数:
- -Xms20m JVM初始分配的内存20m
- -Xmx20m JVM最大可用内存为20m
- -XX:+HeapDumpOnOutOfMemoryError 当JVM发生OOM时,自动生成DUMP文件
- -XX:HeapDumpPath=/Users/mytest/Desktop/dump/ 生成DUMP文件的路径
②栈溢出
栈:虚拟机栈和本地方法栈,关于栈,Java虚拟机规范中描述了两种异常:
StackOverflowError
:线程请求的栈深度大于虚拟机所允许的深度OOM
:如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出
原因:
1. 单个线程下,栈帧太大或虚拟机栈容量太小,内存无法分配2. 不断建立线程
排查思路:
- 查看关键报错信息,确定是StackOverflow还是OOM
- 如果是StackOverflow,检查代码是否存在递归
- 如果是OOM,检查是否有死循环创建线程或调用第三方接口创建线程,通过
-Xss
降低每个线程栈大小
③方法区溢出
方法区(又叫永久代,JDK8之后元空间替换了永久代),用于存放Class的相关信息,如:类名、访问修饰符、常量池、字段描述、方法描述等。运行时产生大量的类,会填满方法区,造成溢出。
溢出原因:
1. 使用CGLib生成大量代理类2. 在Jdk7之前,频繁错误的使用String.intern方法3. 大量jsp和动态产生jsp4. 应用长时间运行,没有重启
排查思路:
- 检查是否永久代空间设置的过小
-XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M
- 是否频繁错误使用String.intern
- 是否与jsp有关
- 是否使用CGLib生成大量代理类
- 重启JVM
④直接内存溢出
直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是,这部分也被频繁的使用,也可能导致OOM。
原因:
1. 本机直接内存不受到Java堆大小限制,但是受到本机总内存大小限制2. 直接内存由-XX:MaxDirectMemorySize指定,如果不指定,默认与Java堆最大值一样(-Xmx)3. NIO程序中,使用ByteBuffer.allocateDirect(capability)分配的是直接内存,可能导致直接内存溢出
排查思路:
- 检查代码是否恰当
- 检查JVM参数
-Xmx(java堆最大值),-XX:MaxDirectMemorySize是否合理
参考:https://zhuanlan.zhihu.com/p/95150243
来源地址:https://blog.csdn.net/weixin_45565886/article/details/129164408
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341