JVM 调优 (2) -- 调优工具


关于常见的线上问题,我们多数会遇到以下问题:

  • 内存泄露
  • 某个进程突然cpu飙升
  • 线程死锁
  • 响应变慢…等等其他问题。

如果遇到了以上这种问题,在线下可以有各种本地工具支持查看,但到线上了,就没有这么多的本地调试工具支持,我们该如何基于监控工具来进行定位问题?

我们一般会基于数据收集来定位,而数据的收集离不开监控工具的处理,比如:运行日志、异常堆栈、GC日志、线程快照、堆快照等。经常使用恰当的分析和监控工具可以加快我们的分析数据、定位解决问题的速度。

1. JDK 命令行工具

JDK 的命令行工具大多数是对 jdk/lib/tools.jar 类库的一层薄包装而已,它们的主要功能代码是在 tools 类库中实现的。Linux 下的这些工具有的甚至是用 shell 脚本编写的。

SUN JDK 监控和故障处理工具:
在这里插入图片描述

1. jps:虚拟机进程状况工具

列出正在运行的虚拟机进程,并显示虚拟机执行的主类名称以及这些进程的本地虚拟机唯一 ID。

jps 命令格式: jps [options] [hostid]

  1. jps 可以通过 RMI 协议开启 RMI 服务的远程虚拟机进程状态,hostid 为 RMI 注册表中注册的主机名。
  2. 如果不指定 hostid 就默认为当前主机或服务器

options 选值:(options 的意思是可以同时使用多个参数选项)

  1. -q: 只输出LVMID,不输出类名、Jar名和传入main方法的参数
  2. -l: 输出 main 类或 Jar 的全限名
  3. -m: 输出传入 main 方法的参数
  4. -v: 输出传入 JVM 的参数

案例:
在这里插入图片描述
在这里插入图片描述

2. jstat:虚拟机统计信息监视工具

jstat 是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载 、内存 、垃圾回收 、JIT编译等运行数据,在没有 GUI 图形界面 、只提供了纯文本控制台环境的服务器上,它会是运行期定位虚拟机性能问题的首选工具。

jstat 的命令格式:jstat option vmid [interval [s|ms] [count]]

option 选值:

  1. -class:用于查看类加载情况的统计,如:jstat -class pid:显示加载 class 的数量,及所占空间等信息。
  2. -compiler:查看 HotSpot 中即时编译器编译情况的统计,如:jstat -compiler pid:显示 VM 实时编译的数量等信息。
  3. -printcompilation:查看 HotSpot 编译方法的统计,如:jstat -printcompilation pid:当前 VM 执行的信息。
  4. -gc:查看 JVM 中堆的垃圾收集情况的统计,如:jstat -gc pid:可以显示 gc 的信息,查看 gc 的次数及时间。其中最后五项,分别是 young gc 的次数,young gc 的时间,full gc 的次数,full gc 的时间,gc 的总时间。
  5. -gccapacity:查看新生代、老生代及持久代的存储容量情况,如:jstat -gccapacity pid:可以显示 VM 内存中三代(young,old,perm)对象的使用和占用大小。
  6. -gccause:查看垃圾收集的统计情况 (这个和 -gcutil 选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因,如:jstat -gccause pid:显示 gc 原因。
  7. -gcnew:查看新生代垃圾收集的情况,如:jstat -gcnew pid:new 对象的信息。
  8. -gcnewcapacity:用于查看新生代的存储容量情况,如:jstat -gcnewcapacity pid:new 对象的信息及其占用量。
  9. -gcutil:查看新生代、老生代及持久代垃圾收集的情况,如:jstat -gcutil pid:统计 gc 信息。
  10. -gcold:用于查看老年代及持久代发生 GC 的情况,如:jstat -gcold pid:查看 old 对象的信息。
  11. -gcoldcapacity: 用于查看老生代的容量,如:jstat -gcoldcapacity pid:查看 old 对象的信息及其占用量。
  12. -gcpermcapacity:用于查看持久代的容量,如:jstat -gcpermcapacity pid:perm 对象的信息及其占用量。

案例:查看 gc 情况:jstat-gcutil 16856
在这里插入图片描述
S0:第一个 Survivor 区的空间使用 (%) 大小
S1:第二个 Survivor 区的空间使用 (%) 大小
E:Eden 区的空间使用 (%) 大小
O:老年代空间使用 (%) 大小
M:方法区空间使用 (%) 大小
CCS:压缩类空间使用 (%) 大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

3. jinfo:虚拟机配置信息查看工具

查看 VM 的配置信息。

命令格式:jinfo [option] pid

option 常用的选值:

  1. -h:查看可以使用的参数选项。
  2. -flag :查看 JVM 参数,如:jinfo -flag MaxMetaspaceSize pid:结果为 -XX:MaxMetaspaceSize=18446744073709486080
  3. -sysprops:查看 Java 的系统配置参数,如:jinfo -sysprops pid

案例:jinfo -flag MaxMetaspaceSize 16856
在这里插入图片描述

4. jmap:java 内存映像工具

jmap 命令用于生成堆转储快照。打印出某个 Java 进程(使用 pid )内存内的所有‘对象’的情况(如:产生哪些对象,及其数量)

jmap 的作用并不仅仅为了获取 dump 文件,它还可以查询 finalize 执行队列 、java 堆和永久代的详细信息,如空间使用率 、当前用的是哪种收集器等。

jmap 命令格式:jmap [option] vmid

option 常用的选值:

  1. -h:查看可以使用的参数选项。
  2. -dump:<path>:生成堆转储快照,如:jmap -dump:format=b,file=E:\hello.hprof 16856
    生成的文件用 VisualVM 装入可以得到:
    在这里插入图片描述
  3. -finalizerinfo:打印正等候回收的对象的信息。
  4. -heap:打印 Java 堆信息。
    在这里插入图片描述
  5. -histo:打印每个类的实例数目,内存占用,类全名信息。VM 的内部类名字开头会加上前缀 ”*”。如果 live 子参数加上后,只统计活的对象数量。
    在这里插入图片描述
    在这里插入图片描述
  6. -F:强迫在 pid 没有响应的时候使用 -dump 或者 -histo 参数,在这个模式下 live 子参数无效
    在这里插入图片描述
    在这里插入图片描述
  7. -permstat:打印 classload 和 jvm heap 持久层的信息。包含每个 classloader 的名字,活泼性,地址,父 classloader 和加载的 class 数量。另外,内部 String 的数量和占用内存数也会打印出来。
  8. -J<flag>:传递参数给 jmap 启动的 jvm。

5. jhat:虚拟机堆转储快照分析工具

JVM 快照分析工具,jhat 命令与 jamp 一般都是搭配使用的,用来分析 jmap 生成的堆快存储快照。jhat 内置了一个微型 http/Html 服务器,可以在浏览器上分析查看。不过建议尽量不要用该内置服务器,因为既然有 dump 文件,那么可以将文件从生产环境拉取下来,然后通过本地可视化工具来分析,这样既减轻了线上服务器压力,又能够分析得足够详尽 (比如 MAT/jprofile/visualVm ) 等。

参数选项:

  1. -h:查看可以使用的参数选项
  2. jhat <file>:分析生产的 dump 文件

案例:jhat E:\test.hprof

test.hprof 是 jmap 生成的 dump 文件,执行 jhat 命令后,当屏幕显示 Server is ready. 的提示后,用户在浏览器中键入 http://localhost:7000 就可以看到分析的结果了。

分析结果默认是以包为单位进行分组显示,分析内存泄漏问题主要会使用到其中的 “Heap Histogram” 与 OQL 标签的功能。前者可以找到内存中总容量最大的对象。后者是标准的对象查询语言,使用类似 SQL 的语法对内存中的对象进行查询统计。

登录 http://localhost:7000 后的界面:
在这里插入图片描述

6. jstack:java 堆栈跟踪工具

jstack 命令用于生成虚拟机当前时刻的线程快照(一般称为 threaddump 或者 javacore 文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程死锁 、死循环 、请求外部资源导致长时间等待等。

注意:尽量少用甚至不要用这个工具

jstack 格式:jstack [option] vmid

参数选项:

  1. -h:查看可以使用的参数选项
  2. -l:长列表,打印关于锁的附加信息,例如属于 java.util.concurrent 的 ownable synchronizers 列表
  3. -m:打印 java 和 native c/c++ 框架的所有栈信息
  4. -F:当jstack [-l] pid没有响应的时候强制打印栈信息

7. HSDIS:JIT 生成代码反汇编

在 Java 虚拟机规范中,详细描述了虚拟机指令集中每条指令的执行过程 、执行前后对操作数栈 、局部变量表的影响等细节。这些细节描述与 Sun 的早期虚拟机(Sun Classic VM)高度吻合,但随着技术的发展,高性能虚拟机真正的细节实现方式已经渐渐与虚拟机规范所描述的内容产生了越来越大的差距,虚拟机规范中的描述逐渐成了虚拟机实现的 “概念模型” ——即实现只能保证规范描述等效。基于这个原因,我们分析程序的执行语义问题(虚拟机做了什么)时,在字节码层面上分析完全可行,但分析程序的执行行为问题(虚拟机是怎样做的、性能如何)时,在字节码层面上分析就没有什么意义了,需要通过其他方式解决。

分析程序如何执行,通过软件调试工具(GDB、Windbg等)来断点调试是最常见的手段,但是这样的调试方式在 Java 虚拟机中会遇到很大困难,因为大量执行代码是通过 JIT 编译器动态生成到 CodeBuffer 中的,没有很简单的手段来处理这种混合模式的调试(不过相信虚拟机开发团队内部肯定是有内部工具的)。因此,不得不通过一些特别的手段来解决问题,基于这种背景,本节的主角—— HSDIS 插件就正式登场了。

HSDIS 是一个 Sun 官方推荐的 HotSpot 虚拟机 JIT 编译代码的反汇编插件,它包含在 HotSpot 虚拟机的源码之中,但没有提供编译后的程序。在 Project Kenai 的网站也可以下载到单独的源码。它的作用是让 HotSpot 的 -XX:+PrintAssembly 指令调用它来把动态生成的本地代码还原为汇编代码输出,同时还生成了大量非常有价值的注释,这样我们就可以通过输出的代码来分析问题。读者可以根据自己的操作系统和 CPU 类型从 Project Kenai 的网站上下载编译好的插件,直接放到 JDK_HOME/jre/bin/clientJDK_HOME/jre/bin/server 目录中即可。如果没有找到所需操作系统(譬如 Windows 的就没有)的成品,那就得自己使用源码编译一下。

还需要注意的是,如果读者使用的是 Debug 或者 FastDebug 版的 HotSpot,那可以直接通过 -XX:+PrintAssembly 指令使用插件;如果使用的是 Product 版的 HotSpot,那还要额外加入一个 -XX:+UnlockDiagnosticVMOptions 参数。

2. JDK 可视化工具

对 JVM 监控的常见可视化工具,除了 jdk 本身提供的 JConsole 和 VisualVm 之外,还有第三方提供的 jprofilter 、perfino 、Yourkit 、Perf4j 、JProbe 、MAT 等。这些工具都极大的丰富了我们定位以及优化 JVM 的方式。

这些工具的使用,网上有很多教程提供,这里就不再过多介绍了。对于 VisualVm 来说,比较推荐使用,它除了对 JVM 的侵入性比较小之外,还是 jdk 团队自己开发的,相信以后功能会更加丰富和完善。对于第三方监控工具 jprofilter,它提供的功能和可视化最为完善,目前多数 IDE 都支持该插件,对于上线前的调试以及性能调优可以配合使用。

另外对于线上 dump 的 heap 信息,应该尽量拉到线下,然后用可视化工具来分析,这样分析更加详细。如果对于一些紧急的问题,必须需要通过线上监控,可以采用 VisualVm 的远程功能来进行,这需要使用 tool.jar 下的 MAT 功能。

1. JConsole

JConsole 工具在 JDK/bin 目录下,启动 JConsole 后,将自动搜索本机运行的 JVM 进程,不需要 jps 命令来查询指定。双击其中一个 JVM 进程即可开始监控,也可使用 远程进程 来连接远程服务器。

2. VisualVM:多合一故障处理工具

VisualVM 是一个集成多个 JDK 命令行工具的可视化工具。VisualVM 基于 NetBeans 平台开发,它具备了插件扩展功能的特性,通过插件的扩展,可用于显示虚拟机进程及进程的配置和环境信息 (jps,jinfo),监视应用程序的CPU、GC、堆、方法区及线程的信息 (jstat、jstack)等。VisualVM 在 JDK/bin 目录下。

VisualVM 的性能分析功能甚至比起 JProfiler、YourKit 等专业且收费的 Profiling 工具都不会逊色多少,而且 VisualVM 还有一个很大的优点:不需要被监视的程序基于特殊 Agent 运行,因此它对应用程序的实际性能的影响很小,使得它可以直接应用在生产环境中。这个优点是 JProfiler、YourKit 等工具无法与之媲美的。

使用 VisualVM 远程连接 Java 进程

3. IDEA 安装 VisualVM 插件及使用

IDEA 下载 visualVM Launcher
在这里插入图片描述
完成之后点击 Restart IDE 即可,重新启动,再次打开 IDEA 后,运行的类上点击右键,右键列表中会有如下两个选项,一个是 Run 一个是 Debug
在这里插入图片描述
第一次点击其中任意一个按钮启动项目的时候,需要配置一些信息:选择 自己路径下的 JDK8/bin/jvisualvm.exe 即可
在这里插入图片描述
点击 OK 后,在我们启动项目的同时,IDEA 会帮我们把 VisualVM 一起自动打开:

在这里插入图片描述
这个软件也就几个功能:
在这里插入图片描述

1. 概述

在这里插入图片描述
如上图所示,概述基本上都是我们的系统属性、运行程序时设置的 JVM 参数等信息的展示。

2. 监视

在这里插入图片描述

监视这个界面的功能还是很有作用的,可以看到 CPU 运行情况、堆的使用情况、类的情况以及线程的动态情况。

因此,我们可以利用这个界面查看 CPU 情况好不好,更重要的是,我们可以查看堆的使用情况,这对于我们分析 JVM 还是非常重要的。

3. 线程

在这里插入图片描述
如上图所以,可以看到所有的线程的情况,是运行、休眠、等待、驻留、监视等情况。

注意, 以上这些都不是关键,关键是VisualVM中还有一个很重要的功能,可以添加插件获取更多的功能。

4. 插件添加

正是因为有了插件的扩展功能,所以这个工具才如此强大,VisualVM 可以做到以下:

  1. 显示虚拟机进程以及进程的配置、环境信息、jps、jinfo。
  2. 监视应用程序的 cpu、GC、堆、方法区以及线程的信息(jstat、jstack)。
  3. dump 以及分析堆转存储快照(jmap、jhat)。
  4. 还有很多其他的功能。

在工具->找到可用插件,安装即可:
在这里插入图片描述

5. 利用 Visual GC 分析虚拟机内存区域

在这里插入图片描述
在这个界面分为以下几个部分。

  1. space(元空间 Metaspace、老年代 Old、新生代(Eden、S0、S1))
  2. Graphs(Compile Time(编译时间)、Class Loader Time(类加载时间)、GC Time(垃圾收集时间)、Eden Space、Survivor 0、Survivor 1、Old Gen、Metaspace)
  3. Histogram(Parameters参数设置)

那么知道这些参数之后,怎么去分析虚拟机到底运行是好是坏呢,这个时候,我们需要了解一些Java虚拟机基础的优化知识。

首先,需要了解一些GC优化的原则。

  1. 多数的Java应用不需要在服务器上进行GC优化;
  2. 多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;
  3. 在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);
  4. 减少创建对象的数量;
  5. 减少使用全局变量和大对象;
  6. GC优化是到最后不得已才采用的手段;
  7. 在实际使用中,分析GC情况优化代码比优化GC参数要多得多;

另外,我们需要知道我们GC优化的目的。

  1. 将转移到老年代的对象数量降低到最小;
  2. 减少full GC的执行时间;

一般,我们需要执行的有以下几点;

  1. 减少使用全局变量和大对象;
  2. 调整新生代的大小到最合适;
  3. 设置老年代的大小为最合适;
  4. 选择合适的GC收集器;

一般我们执行了我们的程序之后,接下来就是需要查看GC的状态了,接着分析结果,判断是否需要进行优化。

一般如果达到以下的指标,就不需要进行GC了。

  1. Minor GC执行时间不到50ms,Minor GC执行不频繁,约10秒一次;
  2. Full GC执行时间不到1s,Full GC执行频率不算频繁,不低于10分钟1次;
6. IDEA 启动项目时配置 JVM 参数

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM调优工具命令详解》是一份预习资料,主要介绍了Java虚拟机(JVM调优过程中使用的一些工具命令。这些工具命令可以帮助开发人员诊断和优化JVM的性能问题。 文中首先介绍了常用的JVM调优工具命令,包括jps、jstat、jinfo、jmap、jhat等。这些命令可以用于查看JVM进程信息、统计JVM内存和线程情况、获取JVM配置参数等。通过使用这些工具命令,开发人员可以快速定位JVM性能瓶颈所在,进行优化。 接下来,文中详细介绍了每个工具命令的使用方法和参数解释。例如,jstat命令可以用于查看JVM内存情况,包括堆内存使用量、垃圾回收情况等。而jmap命令可以用于生成堆内存转储文件,帮助开发人员分析内存泄漏问题。通过掌握这些工具命令的使用,开发人员可以更加高效地进行JVM调优。 此外,文中还介绍了一些实际的调优案例,通过使用这些工具命令来解决实际的JVM性能问题。这些案例包括内存泄漏、线程死锁、CPU占用过高等问题。通过学习这些案例,开发人员可以更好地理解如何利用工具命令来诊断和解决JVM性能问题。 总的来说,《JVM调优工具命令详解》是一份非常实用的预习资料,适合那些需要深入学习JVM性能优化的开发人员。通过学习和掌握这些工具命令,开发人员能够更加高效地进行JVM调优,提升应用程序的性能和稳定性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值