1 编写内存溢出对的代码
package com.study.heap; import java.util.ArrayList; import java.util.List; /** * 测试排查内存溢出的的解决方案 * * @author zhangpba * @date 2021-11-01 */ public class HeapOOM { private int heapObjectNum; public HeapOOM(int heapObjectNum) { this.heapObjectNum = heapObjectNum; } public static void main(String[] args) throws Exception{ List<HeapOOM> list = new ArrayList<>(); // 不断往集合中放入元素,让其内存溢出 int i = 0; while (true){ Thread.sleep(1); System.out.println(i++); list.add(new HeapOOM(i)); } } }
2 配置启动参数
在idea中的Edit Configuration的VM Options中添加如下参数
-verbose:gc -Xms20m -Xmn10m -Xmx20m -XX:+PrintGCDetails -XX:SurvivorRatio=8
-verbose:gc:控制台输出GC日志
-Xms:初始内存大小(memory size)
-Xmn:最小内存
-Xmx:最大内存
-XX:+PrintGCDetails:控制台输出GC具体日志信息
-XX:SurvivorRatio=8:Eden区占比,新生代分为Eden区和Survivor区(from/to Survivor),SurvivorRatio参数定义了Eden、Survivor的比例,默认为8,也就是Eden占新生代的8/10
3 启动测试代码,观察内存中的变化
启动后代码报异常:java.lang.OutOfMemoryError: Java heap space
本地通过visualVM来观察内存中的变化,或者用jmap -heap pid来查看老年代,Eden和s0,s1区域内存占用的情况变化
3.1 visualVM来观察到的变化:
堆中的变化:
在visualVM中,很容易看到锁执行的进程号为:10336
3.2 用jmap -heap pid查看的情况
4 查看最耗内存的对象:jmap -histo:live pid| more
分析出我们写的测试类HeapOOM所创建的对象是导致内存溢出的罪魁祸首。然后针对这个类所涉及的代码进行优化(首先需要对JVM参数进行优化)。
5.OOM优化
二 线程死锁导致OOM1. 实例代码
package com.study.heap; /** * 死锁线程 * * @author zhangpba * @date 2021-11-01 */ public class DeadLock { private Object lockA = new Object(); private Object lockB = new Object(); private void deadLock() { // 定义线程t1,锁定A变量睡眠2秒去抢占B的资源 Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("进入线程t1"); synchronized (lockA) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockB) { System.out.println(Thread.currentThread().getName()); } } } }, "thread-zhangpba-1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println("进入线程t2"); synchronized (lockB) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockA) { System.out.println("线程名:" + Thread.currentThread().getName()); } } } }, "thread-zhangpba-1"); t1.start(); t2.start(); } public static void main(String[] args) { new DeadLock().deadLock(); } }
2.通过visualVM排查线程死锁问题
无死锁
有死锁:会在上面显示红色字体:检测到死锁!生成一个线程 Dump 以获取更多信息
点击线程Dump,可以考到详细死锁信息: