Java虚拟机(五)-调优常用命令

144 阅读6分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

jps

JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。

命令格式

jps [options] [hostid]

option参数

  • -l : 输出主类全名或jar路径
  • -q : 只输出LVMID
  • -m : 输出JVM启动时传递给main()的参数
  • -v : 输出JVM启动时显示指定的JVM参数

其中[option]、[hostid]参数也可以不写。

示例:

image.png

jstat

jstat 可以监测 Java 应用程序的实时运行情况,包括堆内存信息以及垃圾回收信息。

命令格式

jstat [option] LVMID [interval] [count]

option参数

  • -class:显示 ClassLoad 的相关信息;
  • -compiler:显示 JIT 编译的相关信息;
  • -gc:显示和 gc 相关的堆信息;
  • -gccapacity:显示各个代的容量以及使用情况;
  • -gcmetacapacity:显示 Metaspace 的大小;
  • -gcnew:显示新生代信息;
  • -gcnewcapacity:显示新生代大小和使用情况;
  • -gcold:显示老年代和永久代的信息;
  • -gcoldcapacity :显示老年代的大小;
  • -gcutil:显示垃圾收集信息;
  • -gccause:显示垃圾回收的相关信息(通 -gcutil),同时显示最后一次或当前正在发生的垃圾回收的诱因;
  • -printcompilation:输出 JIT 编译的方法信息。

常用介绍

使用jstat 查看堆内存的使用情况。我们可以用 jstat -gc pid 查看:

jstat -gc 62386

image.png

  • S0C:年轻代中 To Survivor 的容量(单位 KB);
  • S1C:年轻代中 From Survivor 的容量(单位 KB);
  • S0U:年轻代中 To Survivor 目前已使用空间(单位 KB);
  • S1U:年轻代中 From Survivor 目前已使用空间(单位 KB);
  • EC:年轻代中 Eden 的容量(单位 KB);
  • EU:年轻代中 Eden 目前已使用空间(单位 KB);
  • OC:Old 代的容量(单位 KB);
  • OU:Old 代目前已使用空间(单位 KB);
  • MC:Metaspace 的容量(单位 KB);
  • MU:Metaspace 目前已使用空间(单位 KB);
  • YGC:从应用程序启动到采样时年轻代中 gc 次数;
  • YGCT:从应用程序启动到采样时年轻代中 gc 所用时间 (s);
  • FGC:从应用程序启动到采样时 old 代(全 gc)gc 次数;
  • FGCT:从应用程序启动到采样时 old 代(全 gc)gc 所用时间 (s);
  • GCT:从应用程序启动到采样时 gc 用的总时间 (s)。

每隔1000ms输出62386的gc情况,一共输出30次

jstat -gc 62386 1000 30

jmap

jmap主要用来查看java进程中的内存占用情况,常见用法:jmap -heap pid,jmap -histo pid ,jmap -dump:live,file={file} pid

命令格式

jmap [option] LVMID

option参数

  • dump : 生成堆转储快照
  • finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
  • heap : 显示Java堆详细信息
  • histo : 显示堆中对象的统计信息
  • permstat : to print permanent generation statistics
  • F : 当-dump没有响应时,强制生成dump快照

jmap -heap pid

这个命令可以看到java进程中jvm 内存使用情况,实例如下:

image.png

如上图所以,可以看到jvm 内存的每个区的使用情况。但是这个值不怎么靠谱,所以这个值仅供参考

 jmap -histo pid

这个命令是用来查看java线程中的对象个数及内存占用大小,示例如下:

image.png

从上图,我们可以看到每个类有多少的对象实例,一共占了多少字节。这个命令很方便的找到大对象。

jmap -dump:live,file={path} pid

我们可以通过 jmap 命令把堆内存的使用情况 dump 到文件中 image.png

我们可以将文件下载下来,使用 MAT 工具打开文件进行分析:

image.png

jstack

jstack用于生成java虚拟机当前时刻的线程快照

命令格式

jstack [option] LVMID

option参数

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

案例 image.png

如果你的程序出现了死锁,在stack.log中看到相应的提示,如:

Found one Java-level deadlock:
=============================
"t2":
  which is held by "t1"
"t1":
  which is held by "t2"
Java stack information for the threads listed above:
===================================================
"t2":
        at testJstack$2.run(testJstack.java:29)
        - waiting to lock <0x8c087670> (a java.lang.Object)
        - locked <0x8c087678> (a java.lang.Object)
"t1":
        at testJstack$1.run(testJstack.java:15)
        - waiting to lock <0x8c087678> (a java.lang.Object)
        - locked <0x8c087670> (a java.lang.Object)
Found 1 deadlock.

线程状态

NEW

至今尚未启动的线程的状态。当使用new一个新线程时,如new Thread(r),但还没有执行start(),线程还没有开始运行,这时线程的状态就是NEW。

RUNNABLE

可运行线程的线程状态。当start()方法被调用时,线程就进入RUNNABLE状态。此时的线程可能正在运行,也可能没有运行

BLOCKED

受阻塞并且正在等待监视器锁的某一线程的线程状态。下列情况会进入阻塞状态:

  • 等待某个操作的返回,例如IO操作,该操作返回之前,线程不会继续下面的代码。
  • 等待某个“锁”,在其他线程或程序释放这个“锁”之前,线程不会继续执行。
  • 等待一定的触发条件。
  • 线程执行了sleep方法。
  • 线程被suspend()方法挂起。

一个被阻塞的线程在下列情况下会被重新激活:

  • 执行了sleep()方法,睡眠时间已到。
  • 等待的其他线程或程序持有的“锁”已被释放。
  • 正在等待触发条件的线程,条件得到满足。
  • 执行了suspend()方法,被调用了resume()方法。
  • 等待的操作返回的线程,操作正确返回。

WAITING

某一等待线程的线程状态。线程因为调用了Object.wait()或Thread.join()而未运行,就会进入WAITING状态。

TIMED_WAITING

具有指定等待时间的某一等待线程的线程状态。线程因为调用了Thread.sleep(),或者加上超时值来调用Object.wait()或Thread.join()而未运行,则会进入TIMED_WAITING状态。

TERMINATED

已终止线程的线程状态。线程已运行完毕。

jstack thread栈信息分析

  手动分析

手动分析需要对jstack的信息比较熟悉,重点关注blocked的线程,waiting for monitor entry,in Object.wait()以及RUNNABLE的线程,然后根据代码具体分析。

  工具分析

线程dump的分析工具:

本文已参与「新人创作礼」活动,一起开启掘金创作之路。