Java技术债务Java技术债务

  •  首页
  •  分类
  •  归档
  •  标签
  • 博客日志
  • 资源分享
  •  友链
  •  关于本站
注册
登录

JVM虚拟机监控与诊断工具

Java,JVM

文章目录

  • jps:查看正在运行的 Java 进程
  • jstat:查看 JVM 统计信息
  • jmap:导出内存映像文件&内存使用情况
  • jhat:JDK 自带堆分析工具
  • jstack:打印 JVM 线程快照
  • jinfo:实时查看和修改 JVM 配置参数
  • jcmd:多功能命令行
  • jstatd:远程主机信息收集

jps:查看正在运行的 Java 进程

显示指定系统内所有 HotSpot 虚拟机进程

语法:

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

* 如果程序参数中添加了 -xx:UsePerfData 参数,命令就无法查询该程序的进程号

jstat:查看 JVM 统计信息

可以显示本地或者远程虚拟机进程中的类加载、内存、垃圾手机、即时编译等运行时数据。

语法:

jstat  -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

<optiopn>: 
        * class: 显示 ClassLoader 的相关信息: 类装载、占用空间、卸载数量、卸载类大小、装载类所消耗的时间。
    gc 相关 ↓
        * gc: 显示与 GC 相关的堆信息。
        * gccapacity: 显示内容与 -gc 基本相同,但输出主要关注 Java 堆各个区域使用的最大、最小空间。
        * gcutil: 显示内容与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比。
        * gccause: 与 -gcutil 功能一样,但是会额外输出导致最后一次或当前正在发生 GC 产生的原因。
        * gcnew: 显示新生代 GC 状况。
        * gcnewcapacity: 显示内容与 -gcnew 基本相同,输出主要关注使用到的最大、最小空间。
        * gcold: 显示老年代 GC 状况。
        * gcoldcapacity: 显示内容与 -gcold 基本相同,输出主要关注使用到的最大、最小空间
        * gcpermcapacity: 显示永久代使用到的最大、最小空间
    JIT 相关 ↓
        * compiler: 显示 JIT 编译器编译过的方法、耗时等信息
        * printcompilation: 显示已经被 JIT编译过的方法
-t:  进程运行的时间
-h<lines>:  在周期性输出数据时,每隔多少行,就输出一个表头
<vmid>: 进程id
<interval>:
        查询间隔,位为毫秒
<count>: 
        查询总次数(和 interval 搭配使用)

堆内存 = 年轻代 + 年老代 + 永久代

年轻代 = Eden区 + 两个Survivor区(From和To)

S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)

EC、EU:Eden区容量和使用量

OC、OU:年老代容量和使用量

PC、PU:永久代容量和使用ssss量

YGC、YGT:年轻代GC次数和GC耗时

FGC、FGCT:Full GC次数和Full GC耗时

GCT:GC总耗时

top -Hp 1容器中所有进程占用CPU内存的情况

注意:如何使用 jstat -gc 来判断是否存在内存泄露:
1、在长时间运行的 Java 程序中,使用 jstat -gc 命令来连续获取多行 GC 内存数据,并取这几行数据列中 OU 列的最小值(即已占用的老年代内存);
2、每隔一段较长时间,重复上述操作,获取多组 OU 列最小值。如果这些值呈现上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此有可能存在内存泄露。

如何使用 jstat -gc -t 来判断堆压力:
我们可以比较 Java 进程的启动时间以及总 GC 时间(GCT列),或则两次测量时间的间隔时间以及总 GC 时间的增量,来得出 GC 时间占运行时间的比例,如果比例较高,说明堆压力大,如果接近 90 %,说明随时都有可能抛出 OOM。

jmap:导出内存映像文件&内存使用情况

获取 dump 文件(堆转储快照的二进制文件)以及获取 Java 进程的内存相关信息,包括 Java 堆各区域的使用情况、堆中对象的统计信息、类加载信息等。(官网推荐用 jcmd)

语法:

jmap [option] pid
jmap [option] <executable <core>>
jmap [option] [server_id@]<remote server IP or hostname>

[option]:
        * -dump: 生成 dump 文件
        * -finalizerinfo: 显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象
        * -heap: 输出整个堆空间的详细信息,包括 GC 的使用、堆配置信息,以及内存的使用信息等。
        * -histo: 输出堆空间中对象的统计信息,包括类、实例数量和合计容量
        * -permstat: 以 ClassLoader 为统计口径输出永久代的内存状态信息
        * -F: 当虚拟机进程对 -dump 选项没有任何响应时,强制执行生成 dump 文件

使用jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。

使用jmap -histo[:live] pid [| more]查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象。注意:此时会先old gc然后再进行统计,避免在线上环境使用。

instance 是对象的实例个数
bytes 是总占用的字节数
class name 对应的就是 Class 文件里的 class 的标识

B 代表 byte
C 代表 char
D 代表 double
F 代表 float
I 代表 int
J 代表 long
Z 代表 boolean
前边有 [ 代表数组, [I 就相当于 int[]
对象用 [L+ 类名表示

用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:

jmap -dump:format=b,file=/tmp/dump.dat pid

dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:

jhat -port 9998 /tmp/dump.dat

注意如果Dump文件太大,可能需要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在浏览器中输入主机地址:9998查看了

jhat:JDK 自带堆分析工具

用于跟 jmap 搭配使用,解析 jmap 生成的 dump 文件。

jhat 命令在 JDK9 及之后中已经被删除,建议使用 VisualVM 代替

语法:

jhat <filename.hprof>

jstack:打印 JVM 线程快照

jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。

语法:

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

例: jstack -l 17792

在 thread dump 中,主要留意以下几种状态

  • 死锁,Deadlock
  • 等待资源,Waiting on condition
  • 等待获取监视器,Waiting on monitor entry
  • 阻塞,Blocked
  • 执行中,Runnable
  • 暂停,Suspended
  • 对象等待中,Object.wait() 或 TIMED_WAITING
  • 停止,Parked

jinfo:实时查看和修改 JVM 配置参数

查询虚拟机配置的参数信息,也可用于调整虚拟机的参数配置

jinfo [options] pid

[options]: 
        * no option: 不输入 option 时,会输出全部的参数和系统属性
        * -flag name: 输出对应名称的参数
        * -flag [+/-]name: 开启或关闭对应名称的参数,只有被标记为 manageable 的参数才可以被动态修改(针对的是 boolean 类型的参数)
        * -flag name=value: 设定对应名称的参数(针对的是 值 类型的参数)
        * -flags: 输出全部的参数
        * -sysprops: 输出系统属性

------- 拓展 -------
命令:
        java -XX:+PrintFlagsInitial:  查询所有 JVM 参数启动的初始值
        java -XX:+PrintFlagsFinal:  查询所有 JVM 参数的最终值
        java -XX:+PrintCommandLineFlags:  查询已经被用户或者 JVM 设置过的详细的 XX 参数的名称和值

jcmd:多功能命令行

在 JDK7 之后,新增的命令工具,可以实现前面除了 jstat 之外所有命令的功能,如导出堆、内存使用、查看 Java 进程、导出线程信息、执行 GC、JVM 运行时间等。(jcmd 拥有 jmap 大部分功能,官网推荐用 jcmd)

语法:

jcmd -l 列出所有的JVM 进程,跟 jps 命令相同
jcmd pid help  列出所有支持的命令
jcmd pid [help 查出来的具体指令]
root@xmars-ai-center-54cd744986-nxbfh:/# jcmd 8 help
8:
The following commands are available:
VM.unlock_commercial_features
JFR.configure
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.
  • Thread.print 可以替换 jstack 指令
  • GC.class_histogram 可以替换jmap中的histo操作
  • GC.heap_dump 可以替换jmap中的dump操作
  • GC.run 可以查看GC的执行情况
  • VM.uptime 可以查看程序的总执行时间,可以替换jstat指令中的t操作
  • VM.system_properties 可以替换 jinfo -sysprops <pid>
  • VM.flags 可以获取JVM的配置参数信息

jstatd:远程主机信息收集

之前的指令只涉及到监控本机的Java应用程序,而在这些工具中,一些监控工具也支持对远程计算机的监控(如jps、jstat)。为了启用远程监控,则需要配合使用jstatd 工具。命令jstatd是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。jstatd服务器将本机的Java应用程序信息传递到远程计算机。

jps:查看正在运行的 Java 进程

显示指定系统内所有 HotSpot 虚拟机进程

语法:

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

* 如果程序参数中添加了 -xx:UsePerfData 参数,命令就无法查询该程序的进程号

jstat:查看 JVM 统计信息

可以显示本地或者远程虚拟机进程中的类加载、内存、垃圾手机、即时编译等运行时数据。

语法:

jstat  -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

<optiopn>: 
        * class: 显示 ClassLoader 的相关信息: 类装载、占用空间、卸载数量、卸载类大小、装载类所消耗的时间。
    gc 相关 ↓
        * gc: 显示与 GC 相关的堆信息。
        * gccapacity: 显示内容与 -gc 基本相同,但输出主要关注 Java 堆各个区域使用的最大、最小空间。
        * gcutil: 显示内容与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比。
        * gccause: 与 -gcutil 功能一样,但是会额外输出导致最后一次或当前正在发生 GC 产生的原因。
        * gcnew: 显示新生代 GC 状况。
        * gcnewcapacity: 显示内容与 -gcnew 基本相同,输出主要关注使用到的最大、最小空间。
        * gcold: 显示老年代 GC 状况。
        * gcoldcapacity: 显示内容与 -gcold 基本相同,输出主要关注使用到的最大、最小空间
        * gcpermcapacity: 显示永久代使用到的最大、最小空间
    JIT 相关 ↓
        * compiler: 显示 JIT 编译器编译过的方法、耗时等信息
        * printcompilation: 显示已经被 JIT编译过的方法
-t:  进程运行的时间
-h<lines>:  在周期性输出数据时,每隔多少行,就输出一个表头
<vmid>: 进程id
<interval>:
        查询间隔,位为毫秒
<count>: 
        查询总次数(和 interval 搭配使用)

堆内存 = 年轻代 + 年老代 + 永久代

年轻代 = Eden区 + 两个Survivor区(From和To)

S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)

EC、EU:Eden区容量和使用量

OC、OU:年老代容量和使用量

PC、PU:永久代容量和使用ssss量

YGC、YGT:年轻代GC次数和GC耗时

FGC、FGCT:Full GC次数和Full GC耗时

GCT:GC总耗时

top -Hp 1容器中所有进程占用CPU内存的情况

注意:如何使用 jstat -gc 来判断是否存在内存泄露:
1、在长时间运行的 Java 程序中,使用 jstat -gc 命令来连续获取多行 GC 内存数据,并取这几行数据列中 OU 列的最小值(即已占用的老年代内存);
2、每隔一段较长时间,重复上述操作,获取多组 OU 列最小值。如果这些值呈现上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此有可能存在内存泄露。

如何使用 jstat -gc -t 来判断堆压力:
我们可以比较 Java 进程的启动时间以及总 GC 时间(GCT列),或则两次测量时间的间隔时间以及总 GC 时间的增量,来得出 GC 时间占运行时间的比例,如果比例较高,说明堆压力大,如果接近 90 %,说明随时都有可能抛出 OOM。

jmap:导出内存映像文件&内存使用情况

获取 dump 文件(堆转储快照的二进制文件)以及获取 Java 进程的内存相关信息,包括 Java 堆各区域的使用情况、堆中对象的统计信息、类加载信息等。(官网推荐用 jcmd)

语法:

jmap [option] pid
jmap [option] <executable <core>>
jmap [option] [server_id@]<remote server IP or hostname>

[option]:
        * -dump: 生成 dump 文件
        * -finalizerinfo: 显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象
        * -heap: 输出整个堆空间的详细信息,包括 GC 的使用、堆配置信息,以及内存的使用信息等。
        * -histo: 输出堆空间中对象的统计信息,包括类、实例数量和合计容量
        * -permstat: 以 ClassLoader 为统计口径输出永久代的内存状态信息
        * -F: 当虚拟机进程对 -dump 选项没有任何响应时,强制执行生成 dump 文件

使用jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。

使用jmap -histo[:live] pid [| more]查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象。注意:此时会先old gc然后再进行统计,避免在线上环境使用。

instance 是对象的实例个数
bytes 是总占用的字节数
class name 对应的就是 Class 文件里的 class 的标识

B 代表 byte
C 代表 char
D 代表 double
F 代表 float
I 代表 int
J 代表 long
Z 代表 boolean
前边有 [ 代表数组, [I 就相当于 int[]
对象用 [L+ 类名表示

用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:

jmap -dump:format=b,file=/tmp/dump.dat pid

dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:

jhat -port 9998 /tmp/dump.dat

注意如果Dump文件太大,可能需要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在浏览器中输入主机地址:9998查看了

jhat:JDK 自带堆分析工具

用于跟 jmap 搭配使用,解析 jmap 生成的 dump 文件。

jhat 命令在 JDK9 及之后中已经被删除,建议使用 VisualVM 代替

语法:

jhat <filename.hprof>

jstack:打印 JVM 线程快照

jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。

语法:

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

例: jstack -l 17792

在 thread dump 中,主要留意以下几种状态

  • 死锁,Deadlock
  • 等待资源,Waiting on condition
  • 等待获取监视器,Waiting on monitor entry
  • 阻塞,Blocked
  • 执行中,Runnable
  • 暂停,Suspended
  • 对象等待中,Object.wait() 或 TIMED_WAITING
  • 停止,Parked

jinfo:实时查看和修改 JVM 配置参数

查询虚拟机配置的参数信息,也可用于调整虚拟机的参数配置

jinfo [options] pid

[options]: 
        * no option: 不输入 option 时,会输出全部的参数和系统属性
        * -flag name: 输出对应名称的参数
        * -flag [+/-]name: 开启或关闭对应名称的参数,只有被标记为 manageable 的参数才可以被动态修改(针对的是 boolean 类型的参数)
        * -flag name=value: 设定对应名称的参数(针对的是 值 类型的参数)
        * -flags: 输出全部的参数
        * -sysprops: 输出系统属性

------- 拓展 -------
命令:
        java -XX:+PrintFlagsInitial:  查询所有 JVM 参数启动的初始值
        java -XX:+PrintFlagsFinal:  查询所有 JVM 参数的最终值
        java -XX:+PrintCommandLineFlags:  查询已经被用户或者 JVM 设置过的详细的 XX 参数的名称和值

jcmd:多功能命令行

在 JDK7 之后,新增的命令工具,可以实现前面除了 jstat 之外所有命令的功能,如导出堆、内存使用、查看 Java 进程、导出线程信息、执行 GC、JVM 运行时间等。(jcmd 拥有 jmap 大部分功能,官网推荐用 jcmd)

语法:

jcmd -l 列出所有的JVM 进程,跟 jps 命令相同
jcmd pid help  列出所有支持的命令
jcmd pid [help 查出来的具体指令]
root@xmars-ai-center-54cd744986-nxbfh:/# jcmd 8 help
8:
The following commands are available:
VM.unlock_commercial_features
JFR.configure
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.
  • Thread.print 可以替换 jstack 指令
  • GC.class_histogram 可以替换jmap中的histo操作
  • GC.heap_dump 可以替换jmap中的dump操作
  • GC.run 可以查看GC的执行情况
  • VM.uptime 可以查看程序的总执行时间,可以替换jstat指令中的t操作
  • VM.system_properties 可以替换 jinfo -sysprops <pid>
  • VM.flags 可以获取JVM的配置参数信息

jstatd:远程主机信息收集

之前的指令只涉及到监控本机的Java应用程序,而在这些工具中,一些监控工具也支持对远程计算机的监控(如jps、jstat)。为了启用远程监控,则需要配合使用jstatd 工具。命令jstatd是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。jstatd服务器将本机的Java应用程序信息传递到远程计算机。

完
  • 本文作者:Java技术债务
  • 原文链接: https://cuizb.top/myblog/article/1642656309
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。
阅读全文
Java技术债务

Java技术债务

Java技术债务
Java技术债务
热门文章
  1. ClickHouse使用过程中的一些查询优化(六)2003
  2. MySQL数据库被攻击,被删库勒索,逼迫我使出洪荒之力进行恢复数据764
  3. MySQL主从同步原理458
  4. 线程池的理解以及使用414
  5. Spring Cloud Gateway整合nacos实战(三)409
分类
  • Java
    30篇
  • 设计模式
    27篇
  • 数据库
    20篇
  • Spring
    18篇
  • MySQL
    13篇
  • ClickHouse
    11篇
  • Kubernetes
    10篇
  • Redis
    9篇
  • Docker
    8篇
  • SpringBoot
    7篇
  • JVM
    6篇
  • Linux
    5篇
  • Spring Cloud
    5篇
  • 多线程
    5篇
  • Netty
    4篇
  • Kafka
    4篇
  • 面经
    4篇
  • Nginx
    3篇
  • JUC
    3篇
  • 随笔
    2篇
  • 分布式
    1篇
  • MyBatis
    1篇
  • 报错合集
    1篇
  • 生活记录
    1篇
  • 源码
    1篇
  • 性能优化
    1篇

最新评论

  • MySQL数据库被攻击,被删库勒索,逼迫我使出洪荒之力进行恢复数据2022-05-06
    Java技术债务:@capture 一起探讨学习,服务器被黑很正常,及时做好备份以及做好防护
  • MySQL数据库被攻击,被删库勒索,逼迫我使出洪荒之力进行恢复数据2022-04-13
    capture:我的刚上线两天,网站里就两篇文章也被攻击了,纳闷
  • Java常用集合List、Map、Set介绍以及一些面试问题2022-01-18
    Java技术债务:HashSet和TreeSet 相同点:数据不能重复 不同点: 1、底层存储结构不同; HashSet底层使用HashMap哈希表存储 TreeSet底层使用TreeMap树结构存储 2、唯一性方式不同 HashSet底层使用hashcode()和equal()方法判断 TreeSet底层使用Comparable接口的compareTo判断的 3、HashSet无序,TreeSet有序
  • undefined2021-12-14
    Java技术债务:如果不指定线程池,CompletableFuture会默认使用ForkJoin线程池,如果同一时间出现大量请求的话,会出现线程等待问题,建议使用自定义线程池。。。
  • undefined2021-12-02
    you:很好,对于小白相当不错了,谢谢
  • CSDN
  • 博客园
  • 程序猿DD
  • 纯洁的微笑
  • spring4all
  • 廖雪峰的官方网站
  • 猿天地
  • 泥瓦匠BYSocket
  • crossoverJie
  • 张先森个人博客
  • 越加网

© 2021-2023 Java技术债务 - Java技术债务 版权所有
总访问量 0 次 您是本文第 0 位童鞋
豫ICP备2021034516号
Java技术债务 豫公网安备 51011402000164号

微信公众号

Java技术债务
Java技术债务

专注于Spring,SpringBoot等后端技术探索

以及MySql数据库开发和Netty等后端流行框架学习

日志
分类
标签
RSS

有不足之处也希望各位前辈指出