内存溢出(OOM)故障排查---JProfiler

上一篇:GC垃圾回收机制----GC回收算法(GC机制必会知识点)

  在java中,因为JVM能够自动回收不再使用的对象而不是人为地显式地销毁对象,所以出现OOM的情况并不多见,但是如果出现了OOM的情况,我们也可以使用一些辅助工具来进行排查。

  JProFiler(java Profiler)就是一款分析OOM的神器,它能够定位出现OOM的代码位置。

1.下载JProfiler客户端

  JProfiler下载地址

  安装很easy,不再赘述……

2.IDEA上下载JProfiler插件

  按住快捷键ctrl+alt+s,选择plugins,搜索JProfiler,下载完毕之后重启IDEA

3.查看JProfiler是否安装成功

  重启IDEA工具之后,应该会在IDEA上看到JProfler的图标
在这里插入图片描述
如果没有此图标,通过如下操作重启IDEA。
在这里插入图片描述

按住ctrl+alt+s,进入Settings,选择Tools下的JProfiler,绑定JProfiler的客户端:
在这里插入图片描述

5.整个OOM测试类

  在我们测试的时候,可以通过参数将内存设置小一些,方便出现OOM的情况,下面参数表示当出现OutOfMemoryError的时候就把文件dump下来。

在这里插入图片描述

堆栈参数

参数作用
-Xmsjvm启动时堆内存的初始大小
-Xmx堆内存的最大值
-Xmn新生代空间大小,剩下的为老年代空间大小
-Xss栈空间大小
-XX:PermGen设置永久代内存的初始化大小,jdk1.8开始废弃永久代
-XX:MaxPermGen设置永久代的最大值
-XX:SUrvivorRatio设置新生代和存活区的比例。-XX:SurvivorRatio=8 表示存活区:新生代=1:8 =》新生代占年轻代的8/10,每个存活区各占年轻代的1/10。默认值:8
-XX:NewRatio设置老年代和年轻代的比例。比如:-XX:NewRatio=8 表示老年代内存:年轻代内存=8:1 => 老年代占堆内存的8/9;年轻代占堆内存的1/9。默认值:2
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

在这里插入图片描述

public class Demo1 {

	public static void main(String[] args) {

		Student student = new Student("张三", 18);
		List<Student> students = new ArrayList<>();

		while (true) {
			students.add(student);
		}
	}


	private static class Student {

		private String name;
		private Integer age;

		public Student(String name, Integer age) {
			this.name = name;
			this.age = age;
		}
	}
}

启动该测试类之后,直接报错如下:
在这里插入图片描述
上图红框中显示已经错误文件java_prd3248.hprof下载下来了,选中当前项目src文件夹,单机右键选择show in explorer
在这里插入图片描述
看到有如下文件:
在这里插入图片描述
双击此文件就可以直接使用JProfiler客户端打开

5.JProfiler客户端分析错误文件

打开后的文件显示如下:
在这里插入图片描述
我们从下面的视图中可以看到是谁占用了大部分的空间:
在这里插入图片描述

也可以选择Thread Dump,它会展示我们程序中的所有线程,通过查看线程我们可以快速定位到底是哪一行代码出了问题:
在这里插入图片描述
错误显示在controller包下的Demo1类中的main方法的第19行出现了问题,然后我们就可以去IDEA工具中查看到底是什么情况了……
在这里插入图片描述

下一篇:Native关键字
<think>好的,用户现在遇到了内存溢出的问题,想知道如何排查和解决OutOfMemoryError。首先,我需要根据提供的引用内容整理出系统的解决方法。根据引用[2],可以用-XX:+HeapDumpOnOutOfMemoryError参数生成堆转储文件,这样就能在OOM发生时获取内存快照。然后,用分析工具比如Eclipse MAT或者VisualVM来分析这个堆转储,找出内存中占用最大的对象,这符合引用[4]提到的观点,内存持续变大是因为对象被持有无法回收。 接下来,用户需要知道具体步骤。首先,重现问题,可能需要压力测试或者特定操作来触发OOM。然后配置JVM参数生成堆转储,分析工具查看大对象,检查是否有内存泄漏,比如集合类未清理或者监听器未注销,这些都是常见的内存泄漏原因。另外,引用[3]提到加载大图片或处理大量数据时容易OOM,所以需要检查资源使用情况,是否有大文件未释放或者缓存策略不当。 此外,优化措施也很重要。比如调整堆内存大小,但要注意不能无限制增加。优化代码逻辑,及时释放资源,使用弱引用等。监控工具如JProfiler可以实时监控内存使用,帮助发现泄漏点。用户可能需要分步骤指导,从生成堆转储到分析,再到修复和验证,每一步都要详细说明。同时,要提醒用户常见陷阱,比如误以为增加内存就能解决问题,而忽视代码层面的优化。最后,生成相关问题,帮助用户进一步理解相关知识点,比如内存泄漏的常见原因或JVM参数的作用。</think>### 内存溢出(OutOfMemoryError)排查与解决方法 #### 1. **生成内存快照(Heap Dump)** 配置JVM参数 `-XX:+HeapDumpOnOutOfMemoryError`,当发生内存溢出时自动生成堆转储文件(*.hprof),用于后续分析[^2]。 ```bash java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof -Xmx512m YourApp ``` #### 2. **分析堆转储文件** 使用工具(如Eclipse MAT、VisualVM、JProfiler)加载.hprof文件: - 查找占用内存最大的对象(如大数组、未释放的集合类) - 检查对象引用链,定位未释放的根源[^4] ![MAT分析示例](https://example.com/mat-screenshot.png) #### 3. **常见问题定位** - **图片/资源未释放**:检查Bitmap、IO流等是否调用`close()`[^3] - **内存泄漏**:监听器未注销、静态集合持有对象、匿名内部类隐式引用 ```java // 错误示例:静态Map未清理导致内存泄漏 public static Map<String, Object> cache = new HashMap<>(); ``` - **数据量过大**:批量处理数据时未分页,或缓存策略不合理 #### 4. **优化措施** - **调整JVM参数**:适当增加堆内存(`-Xmx4g`) - **代码优化**: ```java // 使用WeakHashMap替代强引用 Map<KeyType, ValueType> weakCache = new WeakHashMap<>(); ``` - **监控工具**:使用Android Profiler(Android)或JConsole(Java)实时监控内存波动 #### 5. **验证修复** 通过压力测试复现场景,观察内存曲线是否平稳,OOM是否消失[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值