线上CPU飙高、内存溢出问题分析

线上CPU飙高、内存溢出问题分析

前言

在生产环境,可能会出现CPU飙高,或者内存溢出的情况,造成系统卡顿甚至崩溃,怎样快速定位到问题代码,下面介绍几种方法。

CPU飙高

查看CPU飙高有使用jstack命令及Arthas工具,怎么使用,模拟CPU飙高案例。

public class CPUHighTest {
    public static void main(String[] args){
        new Thread(() -> {
            while (true) {
            }
        }).start();
    }
}

编译:javac CPUHighTest.java,生成class文件
运行:java CPUHighTest
如果运行报错:Error:Could not find or load main class Arthas
需要更改profile文件,在$JAVA_HOME前加.:

CLASSPATH=.:$JAVA_HOME/lib/

使用命令jstack

  1. 使用top -p pid为进程号,现在进行占用CPU情况。
  2. 输入H,显示每个线程占用情况。
  3. 找出占用CPU最高的线程ID为1739613
  4. 需要将线程ID转为十六进制,1a8b5d
  5. 使用命令jstack 1739598|grep -A 10 1a8b5d
    迅速定位到问题代码。

使用Arthas工具

Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

下载Arthas

https://github.com/alibaba/arthas/releases
下载成功后,解压,启动Arthas

java -jar arthas-boot.jar


选择相应的进程,进入arthas
输入dashboard查看概况,发现有CPU占用高的进程


输入thread <进程id>,本例中为9,迅速定位到问题代码

内存溢出

模拟内存溢出

public class OOMTest{
    public static void main(String[] args) {
        List list = new ArrayList<>();
        int i = 0;
        int j = 0;
        while (true) {
            list.add(new User(i++, UUID.randomUUID().toString()));
            new User(j--, UUID.randomUUID().toString());
        }
    }
    private static class User {
        public User(int i, String s) {
        }
    }
}

编译:javac OOMTest.java,生成class文件
运行:设置jvm参数,将堆内存设小一点,方便模拟内存溢出,java -Xms10M -Xmx10M OOMTest

使用jmap导出内存快照

jmap -dump:format=b,file=jvm.hprof 1777262

一般是设置jvm参数自动生成dump文件

java -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/jvm.hprof OOMTest

使用工具分析dump日志

使用jvisualvm

java自带的分析工具,在java的bin目录下


启动成功导入jvm.hprof文件

一般dump文件会比较大,导入jvisualvm时会比较慢,有时会提示内存不足,需要设置jvisualvm启动参数:visualvm_default_options
配置文件位置:JDK路径/lib/visualvm/etc/visualvm.conf


如果电脑内存允许的话,尽可能设置大点




迅速定位到问题代码

使用MAT工具

下载安装
下载地址:https://www.eclipse.org/mat/downloads.php
下载成功后解压,双击MemoryAnalyzer.exe启动


如果本地jdk版本不是11以上,启动过程中可能会报JDK版本问题


这时需要在MemoryAnalyzer.ini中添加参数,设置本地JDK

-vm
C:Program FilesJavajdk-11.0.16binjavaw.exe


启动成功后导入dump文件
file->open heap dump
通过Histogram查看实例占用情况


查看thread_overview


选择占用最高的thread->右键->Thread Details


可迅速找出问题代码。

页面更新:2024-02-18

标签:内存   快照   线程   进程   命令   参数   情况   代码   文件   工具

1 2 3 4 5

上滑加载更多 ↓
Top