JVM命令行工具和JVM调优实战

一、JVM命令行工具

1.JPS(JVM Process Status Tool)

概述: 虚拟机进程工具。
命令格式: jps [option][hostid],例:jps -l
主要选项:

  • -q 只输出LVMID,省略主类的名称
  • -m 输出虚拟机进程启动时传递给主类main()函数的参数
  • -l 输出主类的全名,如果进程执行的是jar包,输出jar路径
  • -v 输出虚拟机进程启动时JVM参数

2.jmap

概述: Java内存映像工具
命令格式: jmap [option] vmid,例:jmap -dump:format=b,file=eclipse.bin 3500
主要选项:

  • -dump 生成Java堆转储快照
  • -finalizerinfo 显示在F-Queue中等待Finalizer线程执行finalize方法的对象
  • -heap 显示Java堆详细信息,如使用哪种回收器,参数设置,分代情况等
  • -histo 显示堆中对象统计信息,包括类、实例数量、合计容量
  • -permstat 以ClassLoader为统计口径显示永久在内存状况
  • -F 当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照

3.jstat

概述: 虚拟机统计信息监视工具
命令格式: jstat [option vmid [interval[s|ms] [count]]],例:jstat -gc 2764 250 20
主要选项:

  • -class 监视类装载,卸载数量,总空间以及类装载所消耗的时间
  • -gc 监视Java堆状况,包括Eden区、两个survivor区,老年代,永久代等的容量、已用空间,GC时间合计等信息
  • -gccapacity 监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间
  • -gcutil 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
  • -gccause 与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
  • -gcnew 监视新生代GC状况
  • -gcnewcapacity 监视内容与-gcnew基本相同,输出主要关注使用到的最大,最小空间
  • -gcold 监视老年代GC状况
  • -gcoldcapacity 监视内容与-gcold基本相同,输出主要关注使用的最大,最小空间
  • -gcpercapacity 输出永久代使用到的最大、最小空间
  • -compiler 输出JIT编译器编译过的方法、耗时等信息
  • -printcompilation 输出已经被JIT编译的方法

4.jinfo

概述: Java配置信息工具
命令格式: jinfo [option] pid,例:jinfo -flag CMSInitiatingOccupancyFraction 1444

5.jstack

概述: Java堆栈跟踪工具
命令格式: jstack [ option ] vmid,例:jstack -l 3500
主要选项:

  • -F 当正常输出的请求不被响应式,强制输出线程堆栈
  • -l 除堆栈外,显示关于锁的附加信息
  • -m 如果调用到本地方法的话,可以显示C/C++的堆栈

6.jhat

概述: 虚拟机堆转储快照分析工具
耗时且极为耗费硬件资源,VisualVM、Eclipse Memory Analyzeer/IBM HeapAnalyzer工具更专业强大

二、JVM调优实战

1.OOM问题排查解决

package com.sonny.classexercise.jvm;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author Xionghaijun
 * @date 2022/9/29 22:56
 */
public class OOMTest {

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

使用JVM参数 -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/xionghaijun/Desktop/jvm.dump 运行程序

将该dump文件导入jvisualvm中
jvisualvm dump图

2.线程死锁

package com.sonny.classexercise.jvm.tuning;

/**
 * @author Xionghaijun
 * @date 2022/10/14 22:44
 */
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("thread1 begin");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {

                }
                synchronized (lock1) {
                    System.out.println("thread1 end");
                }
            }
        }).start();
    }
}

使用 jstack [pid] 查看堆栈信息
死锁信息
“Thread-1” 线程名 prio=5 优先级=5 tid=0x00007fb33608f000 线程id nid=0x4203 线程对应的本地线程标识nid java.lang.Thread.State: BLOCKED 线程状态

线程死锁
也可以使用jvisualvm监控死锁信息
jvisualvm死锁监控

3.CPU过高

package com.sonny.classexercise.jvm.classload;

import com.sonny.classexercise.jvm.User;

/**
 * 类加载:将用户定义的类通过类加载器加载到JVM中
 *
 * @author Xionghaijun
 * @date 2022/9/25 20:21
 */
public class LoadUserClass {

    public static final int INIT_DATA = 2;

    public static User user = User.builder().userId(1L).name("sonny").build();

    public static void main(String[] args) {
        LoadUserClass loadUserClass = new LoadUserClass();
        while (true) {
            loadUserClass.calculate();
        }
    }

    private int calculate() {
        int a = 5;
        int b = 6;
        return (a + b) * INIT_DATA;
    }
}

1.使用 top -p [pid] 命令,显示java进程内存情况,pid是进程号
top命令
2.按 H ,获取每个线程内存情况

4.垃圾回收统计

使用 jstat -gc [pid]
回收统计

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

5.堆内存统计

堆内存统计

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

6.新生代内存统计

新生代内存统计

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

7.老年代垃圾回收统计

老年代垃圾回收统计

  • MC:方法区大小
  • MU:方法区使用大小
  • CCSC:压缩类空间大小
  • CCSU:压缩类空间使用大小
  • OC:老年代大小
  • OU:老年代使用大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

8.老年代内存统计

老年代内存统计

  • OGCMN:老年代最小容量
  • OGCMX:老年代最大容量
  • OGC:当前老年代大小
  • OC:老年代大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

9.元数据空间统计

元数据空间统计

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

gcutil

  • S0:幸存1区当前使用比例
  • S1:幸存2区当前使用比例
  • E:伊甸园区使用比例
  • O:老年代使用比例
  • M:元数据区使用比例
  • CCS:压缩使用比例
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值