前言
上一篇博客总结了一下各种垃圾收集器,这一篇博客总结一下JDK中的一些性能监测工具,为后面的调优实际操作做准备
jps——查看Java进程
这个命令的作用类似于Linux系统下的ps,不同的是jps只是列出java的进程,而且通过jps可以非常方便的查看java的启动类、传入参数和虚拟机参数等信息
准备一个简单的代码
//-XX:+UseSerialGC -XX:+PrintGCDetails
//test,jps
public class JpsTest {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(20000);
}
}
1、不加任何参数
直接列出Main函数简称和进程id号。
2、-q,只显示进程号
3、-m输出传递给进程的参数
4、-v输出传递给进程的虚拟机参数
5、-l输出主函数的完整路径
jstat——查看虚拟机运行时信息
功能很强大,用于观察Java程序运行时的信息。也可以查看堆信息的情况。
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
option的一些含义
option | 含义 |
-class | 显示ClassLoader的相关信息 |
-compiler | 显示JIT编译的相关信息 |
-printcompilation | 输出JIT编译的方法信息 |
-gc | 显示与GC相关的堆信息 |
-gccapacity | 显示各个代的容量及使用情况 |
-gccause | 显示垃圾收集相关信息,同时显示最后一次或当前正在发生的垃圾收集的诱发原因 |
-gcnew | 显示新生代信息 |
-gcnewcapacity | 显示新生代大小与使用情况 |
-gcold | 显示老年代大小 |
-gcoldcapacity | 显示老年代的大小 |
-gcutil | 显示垃圾收集信息 |
其他参数
其他参数 | 含义 |
-t | 在输出信息前加一个timestamp列,显示程序运行时间 |
-h | 在周期性输出数据之后,加入表头 |
interval | 指定输出数据的周期,单位为毫秒 |
count | 指定输出的数据条数 |
1、-class,查看ClassLoder的相关示例
如图所示,显示加载了557个类,占用空间1128byte,耗时0.34
2、-compiler,查看编译信息
如图所示,显示编译了27个类,耗时0.05
3、-printcompilation,输出JIT编译的方法信息
如图所示,compiled显示最近编译的方法数量,size最近编译方法的字节数,type最近编译的方法的编译类型,Method最近编译方法的方法名称标识
-gc
用于统计垃圾回收的信息
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
后续的各种gc开头的参数,其实就是针对分代垃圾收集的统计,这里不再详细举例,参看下面一篇博客——jstat命令详解
jinfo——查看虚拟机参数
查看和设置虚拟机参数,支持在程序运行的时候,修改部分虚拟机参数(并非所有虚拟机参数)。
jinfo [option] <pid>
这里只演示查看
进一步可以参考这篇博客:jinfo命令详解
jmap——获取堆信息
命令格式:
jmap [option] <pid>
jmap [option] <executable <core>
jmap [option] [server_id@]<remote server IP or hostname>
1、heap——显示Java堆详细信息
打印heap的概要信息,GC使用的算法,heap的配置及使用情况,可以用此来判断内存目前的使用情况以及垃圾回收情况
2、-dump——生成堆转储快照
如上图所示:dump命令将堆存储到指定的文件,format指定输出格式,live指定的是活着的对象,file指定转储后的文件名称。生成的文件可以用visual VM和MAT等工具进行分析。
3、-finalizerinfo——打印等待回收的对象信息。
最后输出的Number of objects pending for finalization为0,说明当前的finalization队列中没有等待fializer的线程执行final(这个后续几篇博客会补充)
4、-histo——打印堆的对象统计
统计包括对象数,内存大小等等,jmap -histo:live如下所示:
这个命令执行的时候,会先触发gc,然后再统计信息。
jstack——查看线程堆栈
该命令用于查看并导出Java应用程序的线程堆栈
jstack [-l] <pid>
jstack -F [-m] [-l] <pid>
jstack [-m] [-l] <executable> <core>
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
准备一段如下的代码
public class JstackDemo{
public static void main(String[] args) throws InterruptedException {
Thread thread = new JstackThreadDemo();
thread.start();
}
}
class JstackThreadDemo extends Thread{
@Override
public void run() {
while(true){
System.out.println("stack thread demo ");
}
}
}
运行之后,通过jstack -l [pid] 输出如下结果(具体分析,可能要等总结完多线程之后再详细分析了):
2019-12-10 20:35:58
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
"DestroyJavaVM" #12 prio=5 os_prio=0 tid=0x00000000020c9000 nid=0x1798 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Thread-0" #11 prio=5 os_prio=0 tid=0x00000000535eb000 nid=0x178c runnable [0x00000000543ce000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
- locked <0x0000000083a9fec8> (a java.io.BufferedOutputStream)
at java.io.PrintStream.write(PrintStream.java:482)
- locked <0x0000000083a7ad70> (a java.io.PrintStream)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
- locked <0x0000000083a7ad28> (a java.io.OutputStreamWriter)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.newLine(PrintStream.java:546)
- eliminated <0x0000000083a7ad70> (a java.io.PrintStream)
at java.io.PrintStream.println(PrintStream.java:807)
- locked <0x0000000083a7ad70> (a java.io.PrintStream)
at com.learn.jvm.chapter06.JstackThreadDemo.run(JpsTest.java:20)
Locked ownable synchronizers:
- None
"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000053558800 nid=0x1f88 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000000053537000 nid=0x22b8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000005352b800 nid=0x1e94 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x00000000534d2000 nid=0x1734 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x00000000534d1800 nid=0x20e4 runnable [0x00000000539ce000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x0000000083a81638> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x0000000083a81638> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
Locked ownable synchronizers:
- None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000052bff000 nid=0x1f08 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000052bfe000 nid=0xd2c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000052bd2000 nid=0x1dd8 in Object.wait() [0x000000005300e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000083a81b20> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x0000000083a81b20> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000052b8a800 nid=0x1154 in Object.wait() [0x0000000052e5f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000083a81cd8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x0000000083a81cd8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=2 tid=0x0000000052b81800 nid=0x17f4 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x00000000535e4800 nid=0x1370 waiting on condition
JNI global references: 12
总结
本文只是总结了一些常用的JDK命令,但是这些命令也并不太全,参考的依旧是《实战Java 虚拟机》一书