1. 什么是OOM?
OOM:内存溢出。
2. 造成OOM的原因有哪些?
1)一次性申请了太多的资源。如:一次性从数据库中,查询出过多的数据,导致内存溢出。
2)内存资源资源耗尽,没有得到释放。
3)本身分配的堆内存资源就不够。可以使用jmap -heap来进行查看
3. 如何定位OOM问题?
3.1. 运行的系统已经挂了
这种方式呢,我们在运行系统的时候,添加对应的参数: -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/logs,其中/home/logs为堆内存溢出的路径。
如下所示例子:
我们创建一个SpringBoot项目,在启动类中添加如下代码:
@SpringBootApplication
public class HeapDemoApplication {
public static void main(String[] args) {
SpringApplication.run(HeapDemoApplication.class, args);
List<String> list = new ArrayList<>();
while (true){
list.add(UUID.randomUUID().toString());
}
}
}
创建一个随机的字符串,不断的往list集合中添加。 打包后,我们使用如下命令运行:
java -Xms10M -Xmx10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/ -jar heap-demo-0.0.1-SNAPSHOT.jar &
运行后,出现OOM:
去到对应的日志文件夹下面,可以看到对应的文件。
2.2. 系统运行中,但还未出现OOM的情况
- 我们可以导出dump文件,
jmap -dump:format=b,file=./log/liwei.hprof 进程ID。 - 或者是利用arthas工具。
这两种方式都可以。 这里我们先看第一种情况。
这种情况,我们在排查问题的时候,需要付出成倍的时候或者是更多的时间牌排查问题,为什么呢?
先上图:我们先让我们的程序跑起来:
然后我们使用命令:jmap -histo:live pid,pid指的是进程号。
我们就可以知道是哪一个类占用内存比较高,但是无法具体到哪一行,所以,需要花更多的时间来排查问题。
使用命令导出:jmap -dump:format=b,file=./log/liwei.hprof 进程ID。然后就可以想第一种方式一样,使用visualVM工具来查看。