• 06-JVM-监控及调优案例


    一、常用JVM监控指令

    进程监控-jps

    jps [pid] 查看java进程

    jvm信息查看-jinfo

    1. jinfo -flags [pid] 查看jvm所有参数
    2. **jinfo -flag 【具体参数名称】 【pid】查看具体参数 **
    3. **jinfo -flag name=value 【pid】设置某个参数 **

    信息监控-jstat

    jstat -gc -t -h30 9895 1s 300

    -t:显示系统运行的时间
    -h30:间隔30行数据,输出一次表头
    9895:Java进程ID
    1s:时间间隔
    300:本次输出的数据行数```
    
    ## 堆内信息统计-jmap
    

    jmap工具实际使用方式:jmap -heap [pid]或jmap -dump:live,format=b,file=Dump.phrof [pid]等。
    堆快照导出命令解析:
    live:导出堆中存活对象快照;format:指定输出格式;file:指定输出的文件名及其格式(.dat、.phrof等格式)。```

    堆栈跟踪工具-jstack

    jstack工具主要用于捕捉JVM当前时刻的线程快照,线程快照是JVM中每条线程正在执行的方法堆栈集合。在线上情况时,生成线程快照文件可以用于定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部资源无响应等等原因导致的线程停顿。
    当线程出现停顿时,可以通过jstack工具生成线程快照,从快照信息中能查看到Java程序内部每条线程的调用堆栈情况,从调用堆栈信息中就可以清晰明了的看出:发生停顿的线程目前在干什么,在等待什么资源等。

    jstack -l [pid]

    JVM问题排查

    线上排查OOM异常

    OOM异常大致分为两种,一种是内存溢出,而另一种是内存泄漏

    内存溢出

    内存溢出的出现的场景
    1. 短时间内并发量突然增大
    2. 一次读取过大的对象到内存中,比如报表、excel等大型文件
    3. 一次性从外部将体积过于庞大的数据载入内存,如DB读表、读本地报表文件等。
    4. 程序中使用容器(Map/List/Set等)后未及时清理,内存紧张而GC无法回收。
    5. 程序逻辑中存在死循环或大量循环,或单个循环中产生大量重复的对象实例。
    6. 程序中引入的第三方依赖中存在BUG问题,因此导致内存出现故障问题。
    7. 程序中存在内存溢出问题,一直在蚕食可用内存,GC无法回收导致内存溢出。
    8. 第三方依赖加载大量类库,元空间无法载入所有类元数据,因而诱发OOM。

    问题排查
    获取dump文件至本地,用mat来分析,定位问题位置

    内存泄漏

    出现场景

    1. 存在静态对象引用着不用的对象
    2. 各种资源连接忘记关闭

    排查手段同上

    线程死锁

    排查手段 jps+jstack

    D:\> jps
    19552 Jps
    2892 DeadLock
    
    jstack -l 2892
    

    在这里插入图片描述
    可以从dump日志中明显看出,jstack工具从该进程中检测到了一个死锁问题,是由线程名为T1、T2的线程引起的,而死锁问题的诱发原因可能是DeadLock.java:41、DeadLock.java:25行代码引起的。而到这一步之后其实就已经确定了死锁发生的位置,我们就可以跟进代码继续去排查程序中的问题,优化代码之后就可以确保死锁不再发生。

    CPU100%排查

    1. 通过top指令查看系统后台的进程状态
    [root@localhost ~]# top
    top - 14:09:20 up 2 days, 16 min,  3 users,  load average: 0.45, 0.15, 0.11
    Tasks:  98 total,   1 running,  97 sleeping,   0 stopped,   0 zombie
    %Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
    KiB Mem :   997956 total,   286560 free,   126120 used,   585276 buff/cache
    KiB Swap:  2097148 total,  2096372 free,      776 used.   626532 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
     77915 root      20   0 2249432  25708  11592 S 99.9  2.6   0:28.32 java
       636 root      20   0  298936   6188   4836 S  0.3  0.6   3:39.52 vmtoolsd
         1 root      20   0   46032   5956   3492 S  0.0  0.6   0:04.27 systemd
         2 root      20   0       0      0      0 S  0.0  0.0   0:00.07 kthreadd
         3 root      20   0       0      0      0 S  0.0  0.0   0:04.21 ksoftirqd/0
         5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
         7 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
         8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
         9 root      20   0       0      0      0 S  0.0  0.0   0:11.97 rcu_sched
         .......
    
    1. 通过top -Hp [PID]命令查看该Java进程中,CPU占用率最高的线程:
    [root@localhost ~]# top -Hp 77915
    .....省略系统资源相关的信息......
       PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
     77935 root      20   0 2249432  26496  11560 R 99.9  2.7   3:43.95 java
     77915 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.00 java
     77916 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.08 java
     77917 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.00 java
     77918 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.00 java
     77919 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.00 java
     77920 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.00 java
     77921 root      20   0 2249432  26496  11560 S  0.0  2.7   0:00.01 java
     .......
    
    1. 将线程id转化为16进制,77935–>1306f
    2. 执行 jstack 77915 | grep 1306f
    [root@localhost ~]# jstack 77915 > java_log/thread_stack.log
    [root@localhost ~]# vi java_log/thread_stack.log
    -------------然后再按/,输入线程ID:1306f-------------
    "ActiveThread-Hot" #18 prio=5 os_prio=0 tid=0x00007f7444107800
                nid=0x1306f runnable [0x00007f7432ade000]
       java.lang.Thread.State: RUNNABLE
            at CpuOverload.lambda$main$1(CpuOverload.java:18)
            at CpuOverload$$Lambda$2/531885035.run(Unknown Source)
            at java.lang.Thread.run(Thread.java:745)
    

    三、JVM调优

    内存调优

    当项目执行后,多次手动执行Full GC,查看每次Full GC中老年代剩余对象大小,将堆大小设置为其的3-4倍

    逃逸分析-栈上分配

    JIT会对我们当前方法的局部变量进行分析,若它作用域不超过该方法,则对其进行栈上分配的优化,这样它就不会加载到堆中,有利于减少gc次数

    注意:栈上分配并不是在栈上分配对象,而是对该对象的属性进行标量替换

  • 相关阅读:
    51单片机下实现软件模拟IIC通信
    事件的节流(throttle)与防抖(debounce)
    【crx离线下载】Chrome 商店直接离线下载crx文件的方法
    东北最大城商行退出异地助贷,发力区域自营业务
    DNS系统
    你绝对不知道的接口加密解决方案:Python的各种加密实现
    英语牛津词典 + 例句 + 翻译 + 词性
    【含面试题】MySQL表字段值转换为小写(或大写)的java代码实现
    一文看懂Linux文件的属性
    基础算法练习200题13、判断质数
  • 原文地址:https://blog.csdn.net/qq_42861526/article/details/127112329