Java之JVM监控工具分享

简介: Java之JVM监控工具分享VM的基本知识常用的也就是类加载机制,内存区域、分配、OOM,GC,JVM参数调优 几个链接自己看: 内存区域&类加载机制分配策略&垃圾回收算法、收集器今天结合代码讲一讲常用的java自带工具讲解,这些命令一般都是jdk/lib/tools.jar中。

Java之JVM监控工具分享
VM的基本知识常用的也就是类加载机制,内存区域、分配、OOM,GC,JVM参数调优

几个链接自己看:

内存区域&类加载机制
分配策略&垃圾回收算法、收集器
今天结合代码讲一讲常用的java自带工具讲解,这些命令一般都是jdk/lib/tools.jar中。用来监控诊断我们的Java环境。

官方说明: https://docs.oracle.com/en/java/javase/11/tools/

  1. jps
    显示当前用户的所有java进程的PID 以及主类名

jps : 显示当前用户的所有java进程的PID 以及主类名
jps -v : 打印传递给 Java 虚拟机的参数(如-XX:+UnlockExperimentalVMOptions -XX:+UseZGC)
jps -m : 打印传递给主类的参数
jps -l : 打印模块名以及包名
默认开启(UsePerfData),若加上-XX:-UsePerfData 则无法找到进程。

  1. jstack
    功能 jstack不仅会打印线程的栈轨迹、线程状态(BLOCKED)、持有的锁(locked…)以及正在请求的锁(waiting to lock …),而且还会分析出具体的死锁。

jstack pid : 查看线程情况
jstack -F pid : 正常输出不被响应时,使用该指令
jstack -l pid : 除堆栈外,显示关于锁的附件信息

  1. jstat
    功能 允许用户查看目标 Java 进程的类加载、即时编译以及垃圾回收相关的信息。它常用于检测垃圾回收GC问题以及内存泄漏问题。

显示进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
常用指令

jstat -class pid : 打印类装载、类卸载、总空间以及所消耗的时间
jstat -compiler pid : 打印即时编译相关的数据
jstat -printcompilation pid : 打印即时编译相关的数据
jstat -gc pid 1s 20 : 查询垃圾收集情况,每1秒查询一次,一共查询20次。
jstat -gccause pid : 额外输出上次GC原因
...剩下的都是以-gc为前缀的子命令,它们将打印垃圾回收相关的数据。
加上 -t参数 每行数据之前打印目标 Java 进程的启动时间
我们可以看到,这两个 Survivor 区的容量相等,而且始终有一个 Survivor 区的内存使用量为 0。
在这种情况下,Java 虚拟机会将这块内存区域回收,并标记为可分配的状态。这样子做的结果是,堆中可能完全没有 Survivor 内存区域,因而相应的 S1C 和 S1U 将会是 0。

我们可以比较 Java 进程的启动时间以及总 GC 时间(GCT 列),或者两次测量的间隔时间以及总GC时间的增量,来得出 GC 时间占运行时间的比例。
如果该比例超过 20%,则说明目前堆的压力较大;如果该比例超过 90%,则说明堆里几乎没有可用空间,随时都可能抛出 OOM 异常。

jstat还可以用来判断是否出现内存泄漏。在长时间运行的 Java 程序中,我们可以运行jstat命令连续获取多行性能数据,并取这几行数据中 OU 列(即已占用的老年代内存)的最小值。
然后,我们每隔一段较长的时间重复一次上述操作,来获得多组 OU 最小值。如果这些值呈上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏。

CGC 和 CGCT,它们分别代表并发 GC Stop-The-World 的次数和时间。

S0C:年轻代中第一个survivor(幸存区)的容量 (kb)
S1C:年轻代中第二个survivor(幸存区)的容量 (kb)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (kb)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (kb)
EC:年轻代中Eden(伊甸园)的容量 (kb)
EU:年轻代中Eden(伊甸园)目前已使用空间 (kb)
OC:老年代的容量 (kb)
OU:老年代目前已使用空间 (kb)
MC:元空间的容量 (kb)
MU:元空间目前已使用空间 (kb)
CCSC:压缩类的容量 (kb)
CCSU:压缩类目前已使用空间 (kb)
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

  1. jmap
    功能 生成堆转储快照(heapdump) 用户统计目标 Java 进程的堆中存放的 Java 对象,并将它们导出成二进制文件。查询Java堆和永久代的详细信息,使用率,使用大小,查询finalize执行队列的信息

常用指令

jmap -heap pid : 打印jvm heap的情况
jmap -histo pid : 打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。 并按照内存使用量从多至少的顺序排列
jmap -histo:live pid : JVM会先触发gc,然后再统计信息,只统计堆中的存活对象的情况
jmap -dump:format=b,file=map.log pid: 将内存使用的详细情况输出到文件,之后一般使用其他工具进行分析。同样,-dump:live只保存堆中的存活对象。
jmap -clstats pid : 打印被加载类的信息
jmap -finalizerinfo pid : 该子命令将打印所有待 finalize 的对象。
jmap -permstat pid : 打印permanent generation heap情况
我们通常会利用jmap -dump:live,format=b,file=filename.bin命令,将堆中所有存活对象导出至一个文件之中。
这里format=b将使jmap导出与hprof(在 Java 9 中已被移除)、-XX:+HeapDumpAfterFullGC、-XX:+HeapDumpOnOutOfMemoryError格式一致的文件。这种格式的文件可以被其他 GUI 工具查看。

jmap(以及jinfo、jstack和jcmd)依赖于 Java 虚拟机的Attach API,因此只能监控本地 Java 进程。
一旦开启 Java 虚拟机参数DisableAttachMechanism(即使用参数-XX:+DisableAttachMechanism),基于 Attach API 的命令将无法执行。反过来说,如果你不想被其他进程监控,那么你需要开启该参数。

  1. jhat
    功能 一般与jmap搭配使用,用来分析jmap生成的堆转储文件。

由于有很多可视化工具(Eclipse Memory Analyzer 、IBM HeapAnalyzer)可以替代,所以很少用。不过在没有可视化工具的机器上也是可用的。
常用指令

jmap -dump:format=b,file=map.log pid : 将内存使用的详细情况输出到文件
jhat map.log : 解析Java堆转储文件,并启动一个 web server
演示:https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html

  1. jinfo
    功能 打印目标 Java 进程的配置参数

实时查看和调整虚拟机参数,可以显示未被显示指定的参数的默认值(jps -v 则不能)。

jinfo pid :可用来查看目标 Java 进程的参数,如传递给 Java 虚拟机的-X(即输出中的 jvm_args)、-XX参数(即输出中的 VM Flags),以及可在 Java 层面通过System.getProperty获取的-D参数(即输出中的 System Properties)。

  1. jcmd
    可以用来实现前面除了jstat之外所有命令的功能。

详见 :https://www.jianshu.com/p/388e35d8a09b

  1. javap
  2. 是一个能够将 class 文件反汇编成人类可读格式的工具。 ASM字节码操作:https://blog.csdn.net/ohcezzz/article/details/78416176

默认情况下 javap 会打印所有非私有的字段和方法,
-p 打印私有的字段和方法。
-v 打印所有信息。
-c 查阅方法对应的字节码
附:
一只懂JVM参数的狐狸

代码验证

@Slf4j
public class JvmTest {

private byte[] memory;

public JvmTest(byte[] memory) {
    this.memory = memory;
}

public static void main(String[] args) throws InterruptedException {

    GC测试();
    //死循环();
    //死锁();
}

public static void GC测试() throws InterruptedException {
    for (int i = 1; i < 5; i++) {
        byte[] b = new byte[50 * 1024 * 1024];
        log.info("分配了50M空间给数组");
        Thread.sleep(10000);
    }
    //方法区中常量引用对象 (虚拟机栈(栈帧中的局部变量)中引用的对象 - 方法区中的静态变量引用的对象 - 本地方法栈中JNI(即一般说的Native方法)中引用的对象)
    JvmTest jvmTest = new JvmTest(new byte[50 * 1024 * 1024]);
    log.info("分配了50M空间给对象");
    log.info("调用了System.gc()");
    System.gc();
    jvmTest = null;
    Thread.sleep(10000);
    log.info("调用了System.gc()");
    System.gc();
    Thread.sleep(3000000);
}

public static void 死循环() {
    while (true) {
    }
}

public static void 死锁() {
    String obj1 = "obj1";
    String obj2 = "obj2";
    Runnable r1 = () -> {
        log.info("r1 running");
        while (true) {
            synchronized (obj1) {
                log.info("r1 lock obj1");
                try {
                    //获取obj1后先等一会儿,让Lock2有足够的时间锁住obj2
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj2) {
                    log.info("r1 lock obj2");
                }
            }
        }
    };
    Runnable r2 = () -> {
        log.info("r2 running");
        while (true) {
            synchronized (obj2) {
                log.info("r2 lock obj2");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj1) {
                    log.info("r2 lock obj1");
                }
            }
        }
    };
    Thread a = new Thread(r1);
    Thread b = new Thread(r2);
    a.start();
    b.start();
}

}
原文地址 https://www.cnblogs.com/loveincode/p/10577550.html

相关文章
|
1月前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
36 1
|
1月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
32 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
26天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
26天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
28天前
|
Web App开发 Java
使用java操作浏览器的工具selenium-java和webdriver下载地址
【10月更文挑战第12天】Selenium-java依赖包用于自动化Web测试,版本为3.141.59。ChromeDriver和EdgeDriver分别用于控制Chrome和Edge浏览器,需确保版本与浏览器匹配。示例代码展示了如何使用Selenium-java模拟登录CSDN,包括设置驱动路径、添加Cookies和获取页面源码。
|
29天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
29天前
|
Arthas 监控 数据可视化
JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货
本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
51 2
|
1月前
|
存储 算法 Java
深入理解Java虚拟机(JVM)及其优化策略
【10月更文挑战第10天】深入理解Java虚拟机(JVM)及其优化策略
42 1
|
1月前
|
安全 Java API
🌟探索Java宇宙:深入理解Java技术体系与JVM的奥秘
本文深入探讨了Java技术体系的全貌,从Java语言的概述到其优点,再到Java技术体系的构成,以及JVM的角色。旨在帮助Java开发者全面了解Java生态,提升对Java技术的认知,从而在编程实践中更好地发挥Java的优势。关键词:Java, JVM, 技术体系, 编程语言, 跨平台, 内存管理。
39 2
下一篇
无影云桌面