JVM问题排查

简介: JVM问题排查

本文详细说明了Java应用运行过程中几种常见的JVM相关问题,并给出了问题排查步骤。

一、堆中OOM

现象:Java线程负载过高,JVM内存几乎占满,甚至抛出java.lang.OutOfMemoryError错误。

思路:通过jmap能查看到对内存中实例,可以查看到哪些类的实例比较多,排查出OOM原因。

工具:jmap

步骤

1.查看实例信息:

jmap -histo 14660  #查看历史生成的实例
jmap -histo:live 14660  #查看当前存活的实例,执行过程中可能会触发一次full gc

2.查看堆信息:jmap -heap

image-20230907202201898

3.堆内存dump下来:

(1)jmap -dump:format=b,file=eureka.hprof 14660

(2)使用jvisualvm命令工具导入该dump文件分析

image-20230907204734800

二、死锁排查

现象:多个线程处于死锁状态,无法再正常执行。

背景:当两个线程互相加了对方所依赖的锁时就会进入死锁状态,例如执行以下代码会进入死锁状态:

public class Test1 {
   
   
    public static void main(String[] args) {
   
   
        Object lock = new Object();
        Object lock1 = new Object();
        new Thread(new Runnable() {
   
   
            @Override
            public void run() {
   
   
                synchronized (lock) {
   
   
                    try {
   
   
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
   
   
                        e.printStackTrace();
                    }
                    synchronized (lock1) {
   
   

                    }

                }
            }
        }).start();

        new Thread(new Runnable() {
   
   
            @Override
            public void run() {
   
   
                synchronized (lock1) {
   
   
                    try {
   
   
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
   
   
                        e.printStackTrace();
                    }
                    synchronized (lock) {
   
   

                    }

                }
            }
        }).start();
    }
}

思路:通过jmap能看到所有线程的状态,但线程状态处于blocked时候就是被加锁的状态中。

工具:jmap

步骤

  1. jps 查看进程号

  2. 用jstack 查找死锁状态中线程。

image-20230907205558650

"Thread-1" 线程名

tid=0x000000079582bc98 线程id

nid=0x3e03 线程对应的本地线程标识nid

java.lang.Thread.State: BLOCKED 线程状态

三、CPU飙升

现象:JVM的CPU飙升

思路:通过top查看出占用最大的java线程id,再通过命令top -Hp找到该线程下关联的进程id,找到占用cpu最高的线程id,将其转换为十六进制,在通过jstack来查看进程状态

工具:top+jstack

步骤

  1. 用top命令查找出CPU占用最大的java进程和下面的线程;

查找CPU占用最高的进程:top 查找该进程下面的线程:top -Hp <java_pid>,可以看到该进程下所有子线程,可以找到占用CPU最高的线程Id,可以用命令:printf "%x\n" <线程id> 将十进制线程id转为十六进制,便于后面jstack命令使用打印GC日志:jstat -gc <java_pid> 5000

  1. 用jstack查找出对应线程的日志信息;

通过进程id查看栈内信息:jstack <java_pid> | grep <线程id十六进制值> -A 30(-A 30表示向下打印30行)

image-20230907221120049

总结:cpu飙升可能的原因大概为:

  1. 代码存在死循环,导致消耗cpu;

  2. 代码一直在创建大对象,导致频繁GC,这个时候内存占用率也会很高;

四、频繁Full GC

问题说明:系统中某服务为图方便缓存使用一个hashmap,运行过程中会不断往里面放缓存数据,但是没有考虑这个map的容量问题,结果这个缓存map越来越大,一直占用着老年代的很多空间,时间长了就会导致full gc非常频繁,这就是一种内存泄漏,对于一些老旧数据没有及时清理导致一直占用着宝贵的内存资源,时间长了除了导致full gc,还有可能导致OOM。

这种情况完全可以考虑采用一些成熟的JVM级缓存框架来解决,比如guava、ehcache等自带一些LRU数据淘汰算法的框架来作为JVM级的缓存。

工具:jstat

步骤

  1. jstat -gc 可以评估程序内存使用及GC压力整体情况

image-20230907221503076

  • S0C:第一个幸存区的大小,单位KB
  • S1C:第二个幸存区的大小
  • S0U:第一个幸存区的使用大小
  • S1U:第二个幸存区的使用大小
  • EC:伊甸园区的大小
  • EU:伊甸园区的使用大小
  • OC:老年代大小
  • OU:老年代使用大小
  • MC:方法区大小(元空间)
  • MU:方法区使用大小
  • CCSC:压缩类空间大小
  • CCSU:压缩类空间使用大小
  • YGC:年轻代垃圾回收次数
  • YGCT:年轻代垃圾回收消耗时间,单位s
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间,单位s
  • GCT:垃圾回收消耗总时间,单位s

优化思路:简单来说就是尽量让每次Young GC后的存活对象都留存在年轻代里,尽量别让对象进入老年代,尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响。

JVM参数说明:

-Xms1536M -Xmx1536M -Xmn512M -Xss256K -XX:SurvivorRatio=6  -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M 
-XX:+UseParNewGC  -XX:+UseConcMarkSweepGC  -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly

https://note.youdao.com/yws/public/resource/5cc182642eb02bc64197788c7722baae/xmlnote/4AD3574884C54C7DBF8836737492178E/96307

目录
相关文章
|
7月前
|
监控 Java 索引
cpu使用率过高和jvm old占用过高排查过程
cpu使用率过高和jvm old占用过高排查过程
166 2
|
7月前
|
缓存 算法 安全
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(二)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
67 0
|
7月前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
154 0
|
5月前
|
监控 安全 Java
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
138 2
|
5月前
|
监控 Java Linux
JVM内存问题之如果堆内存一直缓慢上涨,如何解决
JVM内存问题之如果堆内存一直缓慢上涨,如何解决
636 1
|
5月前
|
缓存 算法 Java
JVM内存溢出(OutOfMemory)异常排查与解决方法
JVM内存溢出(OutOfMemory)异常排查与解决方法
|
7月前
|
存储 监控 Java
三万字长文:JVM内存问题排查Cookbook
本文主要系统性地整理了排查思路,为大家遇到问题时提供全面的排查流程,不至于漏掉某些可能性误入歧途浪费时间。
|
7月前
|
Java Linux Arthas
linux上如何排查JVM内存过高?
linux上如何排查JVM内存过高?
1091 0
|
7月前
|
监控 算法 Java
JVM问题排查宝典
本文介绍了JVM问题排查与学习的经验,包括使用VisualVM监控本地JVM、通过GCViewer和gceasy分析GC日志、使用MAT分析OOM以及查询官方JVM参数。还提到了一个第三方网站HeapDump,提供简化版的JVM参数分析和生成服务,以快速生成适合特定环境的JVM配置。此外,推荐了几本深入学习JVM的书籍,并提供了进一步学习JVM问题的资源。
84 1
|
7月前
|
消息中间件 Java 应用服务中间件
深入理解JVM - 如何排查分区溢出问题
深入理解JVM - 如何排查分区溢出问题
92 0