1. 基础概念

  1. 内存溢出(Memory Overflow)指的是程序在请求内存时,向操作体系请求了一块内存空间,但由于某种原因(如程序错误、缺乏足够的内存等),导致程序运用的内存超过了请求到的内存大小。这会导致程序溃散或许呈现未定义的行为。
  2. 内存走漏(Memory Leak)指的是程序在动态分配内存后,没有及时开释现已不需求的内存空间,导致体系中存在很多无用的内存占用,终究可能会导致体系的性能下降或许耗尽可用内存资源。

可以这样了解:内存溢出是指程序需求的内存超过了可用内存;而内存走漏则是指程序自身的内存办理不当,运用了体系供给的内存却没有及时开释。

2. 内存100%事例

堆内存溢出代码示例:

private static List<byte[]> CACHE = new ArrayList<>(1000);
@GetMapping("/tuningTest")
public String tuningTest(){
    for (int loopTimes = 1; loopTimes < 20; loopTimes++) {
        long cacheSize = ObjectSizeCalculator.getObjectSize(CACHE);
        LOGGER.info("第 {} 次循环前, 对象已占用 {} M 内存", loopTimes, cacheSize / 1024 / 1024);
        // 每次占用5M内存
        CACHE.add(new byte[5 * 1024 * 1024]);
    }
    return "OK";
}

启动参数:java -jar -Xms32m -Xmx64m -XX:PermSize=15M -XX:MaxPermSize=30M jvmtest-0.0.1-SNAPSHOT.jar

测试时为了效果明显可以用压测东西,并发数20,次序1000。更有助于剖析问题

2.1 top 指令检查cpu和内存情况

JVM实战系列之CPU100%和内存100%排查

2.2 jmap -heap PID检查jvm内存运用情况

JVM实战系列之CPU100%和内存100%排查

从图中可以看出老年区的内存运用率现已达到了96%

2.3 jstat -gc PID 检查GC的情况

  • YGC : YG GC的次数
  • YGCT:YG GC的均匀时间
  • FGC: FULL GC的次数
  • FGCT:FULL GC的均匀时间

JVM实战系列之CPU100%和内存100%排查

这儿可以连续看几回就会发现FULL GC的次数在疯狂增加,而且FULL GC的均匀时间也会增加,这便是CPU100%的原因,由于CPU一直在尝试废物回收

2.4 jmap -dump:format=b,file=./jmap_dump.hprof PID 运用jmap指令生成剖析所需求用的dump文件。

运用Jprofiler翻开(为什么不必mat,由于我没安装上,不知道为啥)

JVM实战系列之CPU100%和内存100%排查

JVM实战系列之CPU100%和内存100%排查

如上图现已定位出来了问题,这个东西仍是很好用的,有兴趣的大佬们可以研究研究

3. CPU100%事例

代码示例

/**
 * 死循环
 *
 * @return
 */
@RequestMapping("/deadCycle")
public String deadCycle() {
    for (int i = 1; i > 0; i++) {
        System.out.println(i);
    }
    return "Success";
}
/**
 * 死锁
 *
 * @return
 */
@RequestMapping("/deadLock")
public String deadLock() {
    Lock lock1 = new ReentrantLock();
    //线程t1中
    new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (!lock1.tryLock()) {
            System.out.println("线程1 一直自旋获取锁");
        }
        System.out.println("线程1 获取到锁 do something");
    }).start();
    // 线程2
    new Thread(() -> {
        lock1.lock();  //此刻线程2 获取到锁 可是一直阻塞 导致锁无法开释
        while (true) {
        }
    }).start();
    return "Success";
}

这儿就整一个最简单里比如,目的便是为了让CPU一直在运算。

3.1top 指令检查CPU占用100%的进程号

JVM实战系列之CPU100%和内存100%排查

3.2top -H -n 1 -p PID 然后通过指令查找对应进程下线程的状态

JVM实战系列之CPU100%和内存100%排查

3.3然后通过 jstack -l PID > ./jstack.log 指令输出进程的线程文件

jstack.log的文件PID是十六机制,从3.2步骤中咱们可以看出PID为25778的线程CPU特别高,25778二机制为0x64b2。拿到16进制去文件里查找可以很清晰看出哪里呈现了问题

JVM实战系列之CPU100%和内存100%排查
JVM实战系列之CPU100%和内存100%排查