码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • JVM调优工具使用手册


    ​ 作为Java开发人员,我们肯定知道JDK的bin目录下有"java.exe"、"javac.exe"这两个命令工具,这也是我们平时用得最多的工具。但其实bin目录下还有很多工具,这些工具可以帮助我们进行JVM的调优,帮我们定位找出应用程序运行中产生的问题。下面我们来看看其中一些调优工具。

    前置启动程序

    ​ 先启动一个web应用程序,然后用各种JDK自带命令优化应用。

    jps

    jps					
    

    ​ 用jps查看应用进行ID

    jinfo

    jinfo -flags 92604
    

    ​ 此命令可以实时查看和调整虚拟机各项参数。

    jmap

    ​ 此命令可以用来查看内存信息,实例个数以及占用大小,还可以生成堆转储快照。

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

    打开log.txt,内容如下:

    • num:序号
    • instances:实例数量
    • bytes:占用空间大小
    • class name:类名称,[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]

    堆信息

    ​ 可以查看当前应用的堆具体配置、使用信息。

    jmap -heap 92604
    

    转储堆内存dump

    jmap -dump:format=b,file=web.hprof 92604
    

    也可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)

    1. -XX:+HeapDumpOnOutOfMemoryError
    2. -XX:HeapDumpPath=./ (路径)

    示例代码:

    public class OOMTest {
    
       public static List list = new ArrayList<>();
    
       // JVM设置    
       // -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\jvm.dump 
       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()));
          }
       }
    }
    
    

    jvisualvm

    jvisualvm
    

    ​ 该命令可以打开一个可视化界面,监视当前运行应用程序、dump文件进行故障分析等功能。

    ​ 导入上面示例代码运行后产生的hprof文件,可以看到User对象实例数名列前茅。

    jstack

    ​ 此命令可以用来跟踪Java堆栈信息。用于生成虚拟机当前试课的线程快照。快照可以定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。

    死锁示例

    public class DeadLockTest {
    
       private static Object lock1 = new Object();
       private static Object lock2 = new Object();
    
       public static void main(String[] args) {
          new Thread(() -> {
             synchronized (lock1) {
                try {
                   System.out.println("thread1 begin");
                   Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
                synchronized (lock2) {
                   System.out.println("thread1 end");
                }
             }
          }).start();
    
          new Thread(() -> {
             synchronized (lock2) {
                try {
                   System.out.println("thread2 begin");
                   Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
                synchronized (lock1) {
                   System.out.println("thread2 end");
                }
             }
          }).start();
    
          System.out.println("main thread end");
       }
    }
    
    jstack 100516
    

    "Thread-1":线程名

    prio=5: java线程优先级

    os_prio:操作系统线程优先级

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

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

    还可以用jvisualvm自动检测到死锁。

    找出占用cpu最高的线程堆栈信息

    public class Math {
    
        public static final int initData = 666;
        public static User user = new User();
    
        public int compute() {  //一个方法对应一块栈帧内存区域
            int a = 1;
            int b = 2;
            int c = (a + b) * 10;
            return c;
        }
    
        public static void main(String[] args) {
            Math math = new Math();
            while (true){
                math.compute();
            }
        }
    }
    
    

    1,使用命令top -p ,显示你的java进程的内存情况,pid是你的java进程号,比如18963

    2,按H,获取每个线程的内存情况

    3,找到内存和cpu占用最高的线程tid,比如18964

    4,转为十六进制得到 0x4a14,此为线程id的十六进制表示

    5,执行 jstack 18963|grep -A 10 4a14,得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致cpu飙高的调用方法

    6,查看对应的堆栈信息找出可能存在问题的代码

    jstat

    jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下:

    jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]

    注意:使用的jdk版本是jdk8

    整体GC压力情况(常用)

    jstat -gc 103784 2000 1000
    

    ​ 可以评估程序内存使用及GC压力整体情况,监控gc,每2000ms打印输出一次,输出1000次。

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

    堆内存统计

    jstat -gccapacity 103784
    

    • NGCMN:新生代最小容量
    • NGCMX:新生代最大容量
    • NGC:当前新生代容量
    • S0C:第一个幸存区大小
    • S1C:第二个幸存区的大小
    • EC:伊甸园区的大小
    • OGCMN:老年代最小容量
    • OGCMX:老年代最大容量
    • OGC:当前老年代大小
    • OC:当前老年代大小
    • MCMN:最小元数据容量
    • MCMX:最大元数据容量
    • MC:当前元数据空间大小
    • CCSMN:最小压缩类空间大小
    • CCSMX:最大压缩类空间大小
    • CCSC:当前压缩类空间大小
    • YGC:年轻代gc次数
    • FGC:老年代GC次数

    新生代垃圾回收统计

    jstat -gcnew 103784
    

    新生代内存统计

    jstat -gcnewcapacity 103784
    

    • NGCMN:新生代最小容量
    • NGCMX:新生代最大容量
    • NGC:当前新生代容量
    • S0CMX:最大幸存1区大小
    • S0C:当前幸存1区大小
    • S1CMX:最大幸存2区大小
    • S1C:当前幸存2区大小
    • ECMX:最大伊甸园区大小
    • EC:当前伊甸园区大小
    • YGC:年轻代垃圾回收次数
    • FGC:老年代回收次数

    老年代垃圾回收统计

    jstat -gcold 103784
    

    老年代内存统计

    jstat -gcoldcapacity 103784
    

    元数据空间统计

    jstat -gcmetacapacity 103784
    

    • MCMN:最小元数据容量
    • MCMX:最大元数据容量
    • MC:当前元数据空间大小
    • CCSMN:最小压缩类空间大小
    • CCSMX:最大压缩类空间大小
    • CCSC:当前压缩类空间大小
    • YGC:年轻代垃圾回收次数
    • FGC:老年代垃圾回收次数
    • FGCT:老年代垃圾回收消耗时间
    • GCT:垃圾回收消耗总时间

    总结

    ​ 上面介绍到的各个命令,都是JDK提供给我们的最基础的调优工具,如果还有功能更好的,那也是基于上面的基础功能进行开发封装。所以我们只要理解会用上面的各个命令,调优也不是什么问题。

  • 相关阅读:
    Spring Web Flow 2 中流管理的持久化
    java用双大括构造方式进行号初始化赋值操作
    28.【继承与派生 (详解)】
    Espressif-IDE NameError: name ‘websocket‘ is not defined 解决方法
    前端周刊第三十三期
    Apache HTTPD 漏洞复现
    Mybatis的一对一和一对多的标签介绍
    一文解锁vue3中hooks的使用姿势
    线性表重点操作代码集锦
    记一次排查线上MySQL死锁过程,不能只会curd,还要知道加锁原理
  • 原文地址:https://www.cnblogs.com/process-h/p/16877478.html
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号