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 命令

相关推荐
Codiggerworld4 小时前
JVM内存模型——你的对象住在哪里?
jvm
马猴烧酒.6 小时前
【面试八股|JVM虚拟机】JVM虚拟机常考面试题详解
jvm·面试·职场和发展
2301_790300967 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python
m0_736919107 小时前
用Pandas处理时间序列数据(Time Series)
jvm·数据库·python
_F_y7 小时前
C++重点知识总结
java·jvm·c++
爱学习的阿磊8 小时前
使用Fabric自动化你的部署流程
jvm·数据库·python
m0_550024639 小时前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
云姜.10 小时前
线程和进程的关系
java·linux·jvm
heartbeat..10 小时前
JVM 性能调优流程实战:从开发规范到生产应急排查
java·运维·jvm·性能优化·设计规范
玄同76510 小时前
SQLite + LLM:大模型应用落地的轻量级数据存储方案
jvm·数据库·人工智能·python·语言模型·sqlite·知识图谱