JVM-性能调优-命令行篇

官方帮助文档:
https://docs.oracle.com/en/java/javase/11/tools

1.JPS(Java Process Status)

显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),可用于查询正在运行的虚拟机进程。
说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,是唯一的。

基本语法

jps [options] [hostid] ===jps [-q] [-mlvV] [<hostid>]

options参数

-q : 仅仅显示LVMID(local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等。

-l : 输出应用程序主类的全类名 或 如果进程执行的是jar包, 则输出jar包完整路径。

-m : 输出虚拟机进程启动时传递给主类main()的参数 jsp -m -> a.txt 在命令行中输入,先创建a.txt文件,然后将参数信息传入到a.txt文件中。

-v : 列出虚拟机进程启动时的JVM参数。比如: -Xms20m -Xmx50是启动程序指定的jvm参数。

说明:以上参数可以综合使用。

hostid 参数

如果想要远程监控主机上的java程序,需要安装jstatd,不过会容易受到IP地址欺诈攻击,不建议使用,
可以到本地区调用jps命令行。

2.Jstat

用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。常用于检测垃圾回收问题以及内存泄漏问题。

基本语法

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

option参数:

类装载相关的:
-class : 显示Classloader的相关信息 :类的加载、卸载数量、总空间、类装载所消耗的时间等。

垃圾回收相关的:
-gc : 显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。

-gccapacity : 显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。

-gcutil : 显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。

-gccause : 与-gcutil功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。

-gcnew : 显示新生代GC状况。

-gcnewcapacity : 显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间。

-geold : 显示老年代GC状况。

-gcoldcapacity : 显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间。

-gcpermcapacity : 显示永久代使用的最大、最小空间。

interval参数

用于指定输出统计数据的周期,单位为毫秒。即: 查询间隔

count参数

用于指定查询的总次数,如果使用了interval参数,不使用count参数,则一直输出。

-t参数

可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
经验:
我们可以比较Java进程的启动时间以及总GC时间(GCT列),或者两次测量的间隔时间以及总GC时间的增量,来得出GC时间占运行时间的比列。

如果该比例超过20%,则说明目前堆的压力较大;如果该比例超过90%,则说明堆里几乎没有可用空间,随时都可能抛出OOM异常。

-h

可以在周期性数据输出时,输出多少行数据后输出一个表头信息。比如 -h3 每三行输出一个表头。

JIT相关的:

-compiler : 显示JIT编译器编译过的方法、耗时等信息。

-printcompilation : 输出已经被JIT编译的方法。

补充

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

3.Jinfo

查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数,并使之生效。

但是,并非所有参数都支持动态修改。参数只有被标记为manageable的flag可以被实时修改。其实这个修改能力是极其有限的。

可以查看被标记为manageable的参数:
java -XX:PrintFlagsFinal -version | grep manageable

基本语法

jinfo [options] pid 说明:JAVA进程ID必须要加上。

options参数:

no option : 输出全部的参数和系统属性。

-flag name : 输出对应name的参数属性。

-flag [±]name : 开启或者关闭对应名称的参数,只有被标记为manageable的参数才可以被动态修改。

-flag name = value : 设定对应名称的参数。

-flags : 输出全部的参数。

-sysprops : 输出系统属性 等同于java中的System.getProperties()取得的系统参数。

拓展

java -XX:+PrintFlagsInitial 查看所有JVM参数启动的初始值

java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值

java -XX:+PrintCommandLineFlags 查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值

4.Jmap

jmap(JVM Memory Map) :作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。

基本语法

jmap [option] <pid>
jmap [option] <executable> <core> 执行一些核心代码
jmap [option] [server_id@] <remote server IP or hostname> 执行远程的ip

options参数:

-dump :
1.生成Java堆转储快照: dump文件
2.特别的:-dump:live只保存堆中的存活对象

-heap
1.输出整个堆空间得到详细信息,包括GC的使用、堆配置信息,以及内存得到使用信息等

-histo :
1.输出堆中对象的统计信息,包括类、实例数量和合计容量
2.特别的:-histo:live只统计堆中的存活对象

-permstat:
1.以ClassLoader为统计口径输出永久代的内存状态信息
2.仅Linux、Solaris平台生效

-finalizerinfo:
1.显示在F-Queue中等待Finalizer线程执行finalize方法的对象
2.仅Linux、Solaris平台生效

-F:
1.当虚拟机进程对-dump选项没有任何响应时,可使用此选项强制执行生成dump文件

-h | -help
1.jmap工具使用的帮助命令

-J <flag>:
1.传递参数给jmap启动的jvm

参数使用1:导出内存映像文件

1.手动的方式
jmap -dump:format=b,file=<filename.hprof> <pid>
jmap -dump:live,format=b,file=<filename.hprof> <pid>
第二个命令导出所有存活的对象,一般在生产环境中执行的都是这个命令,因为第一个命令导出来所有对象,文件会比较大可能是几十G,而用第二个命令可能才几十m大大缩短了生成和传输的时间。

2.自动的方式
当程序发生OOM退出系统时,一些瞬时信息都随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时。此时若能在OOM时,自动导入dump文件就显得非常迫切了。

这里介绍一种比较常用的取得堆快照文件的方法,即使用:
-XX:+HeapDumpOnOutOfMemoryError : 在程序发生OOM时,导出应用程序的当前堆快照。
-XX:HeapDumpPath=<filename.hprof> :可以指定堆快照的保存位置。

参数使用2:显示堆内存相关信息

1.jmap -heap pid
2.jmap -histo pid

参数使用3:其他作用

1.jmap -permstat pid
2.jmap -finalizeinfo 查看堆积在finalizer队列中的对象

小结

由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就说,由jmap导出的堆快照必定是安全点位置的。这可能导致于该堆快照的分析结果存在偏差。

举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。

另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。

与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,jstat只需要直接读取即可。

5.Jhat

jhat(JVM Heap Analysis Tool)

Sun JDk提供的jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。

使用了jhat命令,就启动了一个http服务,端口是7000,即http://localhost:7000/,就可以在浏览器里分析了。

说明: jhat命令在JDK9、JDK10中已经被删除,官方建议用VisualVM代替。

基本语法

jhat [options] <filename.hprof>

options参数:

-port number 设置jhat HTTP Server的端口号,默认7000
-version 启动后显示版本信息就退出

6.Jstack

jstack(JVM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。

生线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。

在thread dump中,要留意下面几种状态:
死锁,Deadlock(重点关注)
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
阻塞,Blocked(重点关注)
执行中,Runnable
暂停,Suspended

基本语法

jstack [option] pid

options参数(可填可不填):

-F:当正常输出的请求不被响应时,强制输出线程堆栈

-l:除堆栈外,显示关于锁的附加信息

-m:如果调用到本地方法的话,可以显示c/c++的堆栈

7.Jcmd

在JDK1.7以后,新增了一个命令行工具jcmd

它是一个多功能的工具,可以用来实现前面除了jstat之外所有命令的功能。比如:用来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。

jcmd拥有jmap的大部分功能,并且在Oracle的官方网站上也推荐使用jcmd命令代替jmap命令。

基本语法

jcmd -l 列出所有的JVM进程
jcmd pid help 针对指定的进程,列出支持的所有命令
jcmd pid 具体命令 显示指定进程的指令命令的数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值