JVM 内存溢出和死锁检测

内存溢出案例

案例环境

案例代码

bash 复制代码
package com.hero.jvm.memory;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class TestJvmOutOfMemory {
  public static void main(String[] args) {
    List<Object> list = new ArrayList<>();
    for (int i = 0; i < 10000000; i++) {
      String str = "";
      for (int j = 0; j < 1000; j++) {
        str += UUID.randomUUID().toString();
     }
      list.add(str);
   }
    System.out.println("ok");
 }
}

JVM 参数

  1. 让案例尽快 OOM
  2. 开启发生 OOM 时自动 dump 堆快照
bash 复制代码
#参数如下:
-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

执行结果

溢出打印

bash 复制代码
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid31092.hprof ...
Heap dump file created [8453096 bytes in 0.031 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at com.hero.TestJvmOutOfMemory.main(TestJvmOutOfMemory.java:13)

dump 了堆快照文件

导入 MAT 分析

可以看到,有81.72%的内存由Object\[\]数组占有,所以比较可疑。

分析:这个可疑是正确的,因为已经有超过80%的内存都被它占有,这是非常有可能出现内存溢出的。

直接看对象详情

死锁检测

如果在生产环境发生了死锁,我们将看到的是部署的程序没有任何反应了,这个时候我们可以借助jstack进行分析,下面我们实战下查找死锁的原因。

案例环境

java 复制代码
public class TestDeadLock {
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();
    public static void main(String[] args) {
        new Thread(new Thread1()).start();//启动线程01
        new Thread(new Thread2()).start();//启动线程02
    }
    //线程01
    private static class Thread1 implements Runnable {
        @Override
        public void run() {
            synchronized (obj1) {
                System.out.println("Thread1 拿到了 obj1 的锁!");
                try {
                    // 停顿2秒的意义在于,让Thread2线程拿到obj2的锁
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();

                }
                synchronized (obj2) {
                    System.out.println("Thread1 拿到了 obj2 的锁!");
                }
            }
        }
    }
    //线程02
    private static class Thread2 implements Runnable {
        @Override
        public void run() {
            synchronized (obj2) {
                System.out.println("Thread2 拿到了 obj2 的锁!");
                try {
                    // 停顿2秒的意义在于,让Thread1线程拿到obj1的锁
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj1) {
                    System.out.println("Thread2 拿到了 obj1 的锁!");
                }
            }
        }
    }
}

使用 Jstack 分析

命令:jstack 18487 | grep 'BLOCKED' -A 15 --color

发现两个互相等待锁的线程

使用 Arthas 分析死锁

thread-b 命令

相关推荐
晊晌_h19 小时前
嵌入式从0到精通——线程
java·开发语言·jvm
cfm_29141 天前
JDK8+ JVM核心配置参数
jvm
煮煮论英雄1 天前
单文件部署的MQTT轻量级物联网数据平台
jvm·物联网·oracle
wuminyu3 天前
深入剖析 Panama Off-heap 的性能损耗与开销
java·linux·c语言·jvm·c++
uoKent3 天前
c++中new和malloc的区别
java·jvm·c++
~木雨3 天前
String 底层原理与常量池全解析:byte []+coder、intern 陷阱、substring 内存泄漏,一篇讲透
java·jvm·内存优化·string·字符串常量池
cfm_29143 天前
ThreadLocal 内存泄漏
java·jvm
liangbo73 天前
JVM规范第 6 章:Java 虚拟机指令集
java·jvm
2501_937860944 天前
Java多线程初阶(下)—— synchronized、volatile、wait/notify与经典并发工具
java·开发语言·jvm
二十雨辰4 天前
[Java]-JVM面试题
java·开发语言·jvm