【线上问题排查】内存泄漏排查(模拟真实环境)

文章目录

  • 内存泄漏
    • 什么是内存泄漏?
    • 模拟内存泄漏
    • 排查过程


内存泄漏

什么是内存泄漏?

内存泄露 Memory Leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

Memory Leak会最终会导致Out Of Memory!

模拟内存泄漏

写一段 ThreadLocal 模拟内存泄漏的代码。

/**
 * 

* 模拟ThreadLocal内存泄露导致OOM * JVM启动参数 -Xms20M -Xmx20M -Xmn10M *

*/
@GetMapping("/memoryLeak") public void memoryLeak() { // 是否调用remove方法 boolean doRemove = false; // 加锁,让多个线程串行执行,避免多个线程同时占用内存导致的内存溢出问题 final Object lockObj = new Object(); // 开启20个线程 ExecutorService executorService = Executors.newFixedThreadPool(20); // 为了不重复使用线程,用Map标记一下已经已使用过的线程, Map<Long, Integer> threadIdMap = new ConcurrentHashMap<>(); // 循环向线程变量中设置数据 1024 * 1024 = 1M for (int i = 0; i < 20; i++) { executorService.execute(() -> { synchronized (lockObj) { Integer num = threadIdMap.putIfAbsent(Thread.currentThread().getId(), 1); if (num == null) { ThreadLocal<Byte[]> threadLocal = new ThreadLocal<>(); threadLocal.set(new Byte[1024 * 1024]); // 手工回收 System.gc(); try { // 调用GC后不一定会马上回收 Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); } }); } } }

打包部署到服务器。并使用
nohup java -jar -Xms20M -Xmx20M -Xmn10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof & 运行。

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof 参数
是为了发生OOM的时候会自动导出Dump文件

部署之后请求一下接口: http://localhost:8080/memoryLeak
服务器上出现报错信息
【线上问题排查】内存泄漏排查(模拟真实环境)_第1张图片
使用 jstat -gcutil 线程ID 1000 查看,FGC比较频繁,多半是有问题。

【线上问题排查】内存泄漏排查(模拟真实环境)_第2张图片

接下来我们开始排查

排查过程

打开 heapdump.hprof 文件
在这里插入图片描述

文件还是有点大的
我们可以使用JDK自带的 Jvisualvm 打开文件
【线上问题排查】内存泄漏排查(模拟真实环境)_第3张图片
或者执行 jmap -histo:live 进程ID 查看内存中的存活对象
【线上问题排查】内存泄漏排查(模拟真实环境)_第4张图片

Byte[] 占用了空间的 46.7%,基本可以断定为是 Byte[] 没有被回收导致的内存泄漏
然后查看代码中使用到 Byte[] 地方的代码即可定位。

IDEA中可以使用 Ctrl + Shift +R 实现全局搜索

你可能感兴趣的:(问题排查,java,计算机操作系统,架构,安全)