JVM调优的几个常用命令

用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole、大名鼎鼎的VisualVM,IBM的Memory Analyzer等等,但是在生产环境出现问题的时候,一方面工具的使用会有所限制,另一方面所有的工具几乎都是依赖于jdk的接口和底层的这些命令,研究这些命令的使用也让我们更能了解jvm构成和特性,才能将其他强大的工具玩的更转。

Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo下面做一一介绍,最后再附带一个调优案例。

JVM调优基础命令
 

jps(查看进程号)
用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。

一个计算机上,可能运行了相当多的进程。而作为Java开发的我们,只需要去排查我们虚拟机进程是否出现问题。因此往往此命令作为调优的第一步。帮我们筛选出虚拟机进程。

格式

   jps -[ options ] [ hostid ] (运行的进程不多时,直接打JPS就行)

参数说明

      options

         -q   只输出java进程的进程id

 

         -l    输出java进程的进程id和main方法的类全名

         -m  输出java进程的进程id和main方法的入参

         -v   输出java进程的进程id和jvm的入参   常用命令

         -V   输出java进程的进程id和通过flag文件传入jvm的参数

      hostid

         命令对应的服务器ip,默认不加参数,代码查看本机

 

jstat(

在我们对程序进行问题排查时,或许在多个时间点排查问题都是正常的。那么就需要用到这个指令,在一段时间内持续反馈各项指标数据。

格式

 jstat -[ options ] [ hostid ] [ 时间/毫秒 ] [ 统计次数 ]

例子:jstat -gc 23892 5000 20

参数说明

  options

 -class(类加载器)

-compiler(JIT)

-gc (GC堆状态)

-gccapacity(各区大小)

-gcnew(新区统计)

-gcnewcapacity(新区大小)

-gcold (老区统计)

-gcoldcapacity (老区大小)

-gcpermcapacity (永久区大小)

-gcutil (GC 统计汇总)

-printcompilation (HotSpot 编译统计)

      hostid

         命令对应的服务器ip,默认不加参数,代码查看本机

 

可以看到,这个指令的核心正是,把时间点的统计变为了时间片的统计。由此我们可以大概估测一下,未来更强大的排查工具可以以此绘制出数据变化趋势图。在此,我们依然使用基础的指令来做一个小例子。

第一步,我们先根据JPS指令,获取到我们的Java进程号为23892。

 

假设需要5000毫秒查询一次此进程的垃圾收集状况,一共查询20次。那么命令应当是jstat -gc 23892 5000 20。查询结果如下:

JDK1.5

JDK1.8 

 

-gc 指令参数解释

S0C:第一个幸存区(From 区)的大小

S1C:第二个幸存区(To 区)的大小

S0U:第一个幸存区的使用大小

S1U:第二个幸存区的使用大小

EC:伊甸园(Eden)区的大小

EU:伊甸园(Eden)区的使用大小

OC:老年代大小OU:老年代使用大小

MC:方法区大小

MU:方法区使用大小

CCSC:压缩类空间大小

CCSU:压缩类空间使用大小

YGC:年轻代垃圾回收次数

YGCT:年轻代垃圾回收消耗时间

FGC:老年代垃圾回收次数

FGCT:老年代垃圾回收消耗时间

GCT:垃圾回收消耗总时间

jstat显示的参数太多,眼都看花了怎么办

当然,这么一堆数据,看着也不方便。我们的工具还提供了筛查部分参数的功能。例如我们只想看垃圾回收的次数,就可以使用命令:

jstat -gc 23892 5000 20 | awk '{print $13,$14,$15,$16,$17}'

 

jinfo(查看/修改虚拟机参数)
我们知道,许多时候,我们的Java进程出现了问题,并非一定是代码出现了问题。

实际上我们的JVM有许许多多的功能,但平常我们却很少使用。而在程序运行期间,我们往往需要临时开启这些功能,协助我们排查问题,或加强一些功能。

来看看我们我们虚拟机的参数设置情况,包括Java System属性和JVM命令行参数。
也可以动态的修改正在运行的 JVM 一些参数.(打破限制器)
当系统崩溃时,jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息
格式

 jinfo -[ options ] [ hostid ]

例子:jinfo -flag PrintGC 13528

参数说明

-flags pid :打印当前VM的参数

-flag <name> pid:打印指定JVM的参数值 

-flag [+|-]<name> pid:设置指定JVM参数的布尔值

-flag <name>=<value> pid:设置指定JVM参数的值

-sysprops  pid : 获取当前系统参数包括-D设置的参数

 当然并不是所有的参数都是允许修改的,只允许修改其中部分参数。。

如何查看哪些参数可修改

在 windows 上可以通过以下 java -XX:+PrintFlagsFinal –version 查询所有-XX 的参数

注意:manageable 的参数,代表可以运行时修改。

 

首先我们由上图得知PrintGC这个XX参数是可以运行时修改的。

jinfo –flag [+/-][参数] pid 可以修改参数

还是这段程序,我们的关注点在于,启动程序后,控制台并没有任何打印。此时,我们通过jinfo命令让其在不关闭程序的状态下显示出GC打印信息。

我们打开命CMD窗口,通过jps定位到相关进程,再通过jinfo -flag PrintGC 23892查看PrintGC这个参数的当前状态。

可以很明显看到。我们查到的该参数前面有个减号。这说明,此时这个参数是关闭的。此时,我们用jinfo -flag +PrintGC 23892指令。打开该参数。

此时,我们再返回控制台,发现GC日志已经打开了。

总结

通过jinfo命令,我们可以再生产环境上临时打开GC日志,或者进行一些数据的配置。(不需要重启应用的条件下),也是我们去排查问题的关键命令。

 

jmap(堆,对象详情,导出dump日志)
我们都知道,堆内存往往使我们调优的重中之重。无论是OOM,还是垃圾回收的回收频率,都与堆内存有着千丝万缕的联系。而堆内存中说白了就存的就是对象。那么jmap就可以给我们提供所有对象的信息,以及堆的各项数据信息。

同时,我们知道对象信息是相当多的。仅仅是CMD窗口是无法显示完的。因此,我们也可以到成dump日志,来仔细分析。

格式(具体使用例子看options说明)

jmap [option] <pid>

       (to connect to running process) 连接到正在运行的进程

jmap [option] executable <core>

       (to connect to a core file)     连接到核心文件

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

       (to connect to remote debug server) 连接到远程调试服务

命令中的连接参数说明

(一般我们自己本机使用jmap [option] <pid>指令即可):

executable 可能是产生core dump的java可执行程序

core 将被打印信息的core dump文件

remote-hostname-or-IP 远程debug服务的主机名或ip

server-id 唯一id,假如一台主机上多个远程debug服务 

常用options说明

由于jmap的使用较为复杂,因此提供每一个指令的具体写法,方便在开发中直接使用。

-dump:[live,]format=b,file=<filename>(重点使用)

使用hprof二进制形式,输出jvm的heap(堆)内容到文件,[live]子选项是可选的,假如指定live选项,那么只输出活的对象到文件。整个dump日志导出了Java进程在某一时刻的所有堆内存信息。

带live的输出格式:

jmap -dump:live,format=b,file=myjmapfile.txt 23892

全部输出格式:

jmap -dump:format=b,file=myjmapfile.txt 23892

运行结果:

即可在/root目录打开myjmapfile.txt文件。

当然,file=后面也可以指定文件存放的目录,就可以在指定目录查看文件了。

-finalizerinfo 

打印正等候回收的对象的信息.

输出格式:

jmap -finalizerinfo 19570

运行结果:


Number of objects pending for finalization: 0 (等候回收的对象为0个)

-heap(重点使用)

 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况。整个堆的概要信息就可以从上帝视角一览无遗。

输出格式:

jmap -heap 19570

运行结果:

-histo[:live] (重点使用)

打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量。

采用jmap -histo pid>a.log日志将其保存,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。

jmap -dump:format=b,file=outfile 19570可以将19570进程的内存heap输出出来到outfile文件里,再配合MAT(内存分析工具)。

带live输出格式:

jmap -histo:live 19570

全部输出格式:

jmap -histo 19570

 

-permstat

 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来. 

输出格式:

jmap -permstat 19570

 

 

jhat(查看jmap导出的dump日志)
dump日志往往相当大,我们无法直接对其进行分析。因此,jhat指令正是为分析dump日志而存在的。

格式

jhat [ options ]<dump>

例子:jhat D:/tomcat.bin

有时你dump出来的堆很大,在启动时会报堆空间不足的错误,可以使用如下参数:

jhat -J-Xmx512m <dump>

jhat -J-Xmx1024m D:/tomcat.bin

参数设置

-J< flag > 因为 jhat 命令实际上会启动一个JVM来执行, 通过 -J 可以在启动JVM时传入一些启动参数. 例如, -J-Xmx512m 则指定运行 jhat 的Java虚拟机使用的最大堆内存为 512 MB. 如果需要使用多个JVM启动参数,则传入多个 -Jxxxxxx

-stack false|true 关闭跟踪对象分配调用堆栈。如果分配位置信息在堆转储中不可用. 则必须将此标志设置为 false. 默认值为 true.

-refs false|true 关闭对象引用跟踪。默认情况下, 返回的指针是指向其他特定对象的对象,如反向链接或输入引用(referrers or incoming references), 会统计/计算堆中的所有对象。

-port port-number 设置 jhat HTTP server 的端口号. 默认值 7000。

-exclude exclude-file 指定对象查询时需要排除的数据成员列表文件。 例如, 如果文件列出了 java.lang.String.value , 那么当从某个特定对象 Object o 计算可达的对象列表时, 引用路径涉及 java.lang.String.value 的都会被排除。

-baseline exclude-file 指定一个基准堆转储(baseline heap dump)。 在两个 heap dumps 中有相同 object ID 的对象会被标记为不是新的(marked as not being new). 其他对象被标记为新的(new). 在比较两个不同的堆转储时很有用。

-debug int 设置 debug 级别. 0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息。

-version 启动后只显示版本信息就退出。

 

使用小技巧

首先先找到dump文件的目录,使用指令:jhat -J-Xmx1024m D:/tomcat.bin

这样就启动起来了一个简易的HTTP服务,端口号是7000,尝试一下用浏览器访问一下它,本地的可以通过http://localhost:7000,就可以得到页面:


 

jstack(栈详情,排查死锁,死循环,请求资源超时神器)
我们学了jmap,知道它主要负责堆和对象的信息管理。而运行时数据区中的栈区,同样占有不可忽略的地位。

jstack是jdk自带的线程堆栈分析工具,使用该命令可以查看或导出 java 应用程序中线程堆栈信息。

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

由此总结出,这个指令如果派上用场了,那多半是你的代码有问题,该挨板子了!

格式

jstack [ option ] pid

查看当前时间点,指定进程的dump堆栈信息。

jstack [ option ] pid > 文件

将当前时间点的指定进程的dump堆栈信息,写入到指定文件中。注:若该文件不存在,则会自动生成;若该文件存在,则会覆盖源文件。

jstack [ option ] executable core

查看当前时间点,core文件的dump堆栈信息。

jstack [ option ] [server_id@]<remote server IP or hostname>

查看当前时间点,远程机器的dump堆栈信息。

参数说明

      options

        -F   当进程挂起了,此时'jstack [-l] pid'是没有相应的,这时候可使用此参数来强制打印堆栈信息,强制jstack),一般情况不需要使用。

       -m   打印java和native c/c++框架的所有栈信息。可以打印JVM的堆栈,以及Native的栈帧,一般应用排查不需要使用。

       -l 长列表. 打印关于锁的附加信息。例如属于java.util.concurrent的ownable synchronizers列表,会使得JVM停顿得长久得多(可能会差很多倍,比如普通的jstack可能几毫秒和一次GC没区别,加了-l 就是近一秒的时间),-l 建议不要用。一般情况不需要使用。

       -h or -help 打印帮助信息。

使用小技巧

jps查看java进程:

临时查看:jstack查看指定进程的当前堆栈情况:


持久化查看:将指定进程的当前堆栈情况记录到某个文件中:


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值