提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
01-概述
简单命令行工具
02 jps:查看正在运行的Java进程
基本情况
测试
我们这里在windows下演示jps的使用
首先打开命令行窗口,输入jps
public class ScannerTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String info = scanner.next();
}
}
本地虚拟机ID和操作系统的进程ID是一致的。
基本语法
可以通过 jps -help 来查看对应的参数信息
options参数
综合使用:
jps -l -m等价于jps -lm
如何将信息输出到同级文件中:
语法:命令 > 文件名称
例如:jps -l > a.txt
【-q 】
【-l 】
【-m】:输出虚拟机进程启动时传递给主类main()的参数
public class ScannerTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String info = scanner.next();
}
}
【-v】:列出虚拟机启动时的JVM参数。
补充:如果某Java进车关闭了默认开启的UsePerfData参数(即使用参数:-XX:-UsePerfData),那么jps命令(以及下面介绍的jstat)将无法探知该java进程。
hostid参数
03-jstat:查看JVM统计信息
基本情况
基本语法
其中vmid是进程id号,也就是jps之后看到的前面的号码,如下:
option参数
public class ScannerTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String info = scanner.next();
}
}
先以【-class】为例,讲解jstat的用法
【interval参数】
用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
【count参数】
用于指定查询的总次数
interval和count只写一个的话,他会认为你是interval
【-t参数】
可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
【-h参数】
可以在周期性数据输出时,输出多少行数据后输出一个表头信息
各种option参数的用法
JIT相关的
- -compiler:显示JIT编译器编译过的方法、耗时等信息。
- -printcompilation :输出已经被JIT编译过的方法
垃圾回收相关的
-
-gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等容量、已用空间、GC时间合计等信息。
-
-gccapacity:显示内容与-gc基相同,但输出主要关注Java堆各个区域使用的最大、最小空间
-
-gcutils:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-
-gccause:与-gcutil功能相同,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。
-
-gcnew:显示新生代GC状况
-
-gcnewcapacity:显示内容与-gcnew基本相同,但输出主要关注使用到的最大、最小空间
-
-gcold:显示老年代GC状况
-
-gcoldcapacity:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
-
-gcpermcapacity:显示永久代使用到的最大、最小空间
/**
* @author shkstart
* @create 17:49
* -Xms60m -Xmx60m -XX:SurvivorRatio=8
*/
public class GCTest {
public static void main(String[] args) {
ArrayList<byte[]> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
byte[] arr = new byte[1024 * 100];//100KB
list.add(arr);
try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
jstat 如何排查OOM和内存泄漏
其实上述代码最终发生OOM
怎么查看呢?
我们重新启动上述代码
新启动的进程号为3956可以用 -gcutils监控jvm内存的占比情况:
我们也可以通过 -gccause打印产生gc的原因
经验:
(0.020-0.004)/(31.6-30.6)
04-jinfo:实时查看和修改JVM配置参数
基本情况
基本语法
查看
- jinfo -sysprops 进程id :可以查看由System.getProperties()取得的参数
- jinfo -flags 进程id:查看曾经赋过值的一些参数
- jinfo -flag 参数名称 进程id:查看某个java进程的具体参数信息
修改
-
针对boolean类型:jinfo -flag [+|-]参数名称 进程id
如果使用+号,那就可以让该参数起作用,否则使用-号就让该参数不起作用,具体例子如下:
-
针对非boolean类型:jinfo -flag 参数名称=参数值 进程id
修改只对当前进程有效
拓展
- java -XX:+PrintFlagsInitial:查看所有JVM参数启动的初始值
- java -XX:+PrintFlagsFinal:查看所有JVM参数的最终值
- java -参数名称:+PrintCommandLineFlags:查看那些已经被用户或者JVM设置过的详细的XX参数的名称和值
05-jmap:导出内存映像文件&内存使用情况
基本情况
基本语法
- -dump:生成Java堆转储快照:dump文件
特别的:-dump:live只保存堆中的存活对象
- -heap:输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等.
- -histo:输出堆中对象的同级信息,包括类、实例数量和合计容量
特别的:-histo:live只统计堆中的存活对象
- -permstat:以ClassLoader为统计口径输出永久代的内存状态信息
仅linux/solaris平台有效
- -finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象
仅linux/solaris平台有效
- -F:当虚拟机进程对-dump选项没有任何响应时,可使用此选项强制执行生成dump文件
仅linux/solaris平台有效
- -h | -help:jamp工具使用的帮助命令
- -J < flag>:传递参数给jmap启动的jvm
使用1:导出内存映像文件
1、手动的方式:
- jmap -dump:format=b,file=<filename.hprof> < pid>
- jmap -dump:live,format=b,file=<filename.hprof> < pid>(生产生多使用这种,这个只保存存活的对象,因此较小一些)
/**
* @author shkstart
* @create 17:49
* -Xms60m -Xmx60m -XX:SurvivorRatio=8
*/
public class GCTest {
public static void main(String[] args) {
ArrayList<byte[]> list = new ArrayList<>();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 1000; i++) {
byte[] arr = new byte[1024 * 100];//100KB
list.add(arr);
try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
注意:这个dump文件是二进制文件,因为我电脑安装了Jprofile,所以d盘生成的文件是这样子,它用记事本是打不开的。
打开是这种乱码。。。
dump文件的打开方式有很多种:jprofile、jconsole、MAT、以及后面说的指令jhat
另外,我们可以看出文件4是比较小的,因为jmap -dump:live,format=b,file=<filename.hprof> < pid>只会保存存活的对象,生产上也建议如此。
2、自动的方式
手动的方式获取dump文件是随时随意的,但是自动的方式是在系统OOM时生成dump文件
public class GCTest {
public static void main(String[] args) {
ArrayList<byte[]> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
byte[] arr = new byte[1024 * 100];//100KB
list.add(arr);
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
使用2:显示堆内存相关信息
-
jmap -heap 进程id
jmap -heap 进程id只是时间点上的堆信息,而jstat后面可以添加参数,可以指定时间动态观察数据改变情况,而图形化界面工具,它们可以用图表的方式动态展示出相关信息,更加直观明了
Attaching to process ID 12792, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.152-b16
using thread-local object allocation.
Parallel GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 62914560 (60.0MB)
NewSize = 20971520 (20.0MB)
MaxNewSize = 20971520 (20.0MB)
OldSize = 41943040 (40.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 16777216 (16.0MB)
used = 2276224 (2.1707763671875MB)
free = 14500992 (13.8292236328125MB)
13.567352294921875% used
From Space:
capacity = 2097152 (2.0MB)
used = 0 (0.0MB)
free = 2097152 (2.0MB)
0.0% used
To Space:
capacity = 2097152 (2.0MB)
used = 0 (0.0MB)
free = 2097152 (2.0MB)
0.0% used
PS Old Generation
capacity = 41943040 (40.0MB)
used = 31980832 (30.499298095703125MB)
free = 9962208 (9.500701904296875MB)
76.24824523925781% used
1766 interned Strings occupying 158112 bytes.
- jmap -histo 进程id:输出堆中对象的同级信息,包括类、实例数量和合计容量,也是这一时刻的内存中的对象信息
使用3:其他作用
这两个指令仅linux/solaris平台有效,所以无法在windows操作平台上演示,并且使用比较小众,不在多说
- jmap -permstat :查看系统的ClassLoader信息
- jmap -finalizerinfo:查看堆积在finalizer队列中的对象
小结
06-jhat:JDK自带堆分析工具(了解)
jhat命令在jdk9及其之后就被移除了,官方建议使用jvisualvm代替jhat,所以该指令只需简单了解一下即可
其中dumpfile代表dump文件的地址以及名称,例如:
options参数
举例如下:
07-jstack:打印JVM中线程快照
基本情况
基本语法
public class ThreadDeadLock {
public static void main(String[] args) {
StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();
new Thread(){
@Override
public void run() {
synchronized (s1){
s1.append("a");
s2.append("1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2){
s1.append("b");
s2.append("2");
System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (s2){
s1.append("c");
s2.append("3");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1){
s1.append("d");
s2.append("4");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2022-05-07 20:03:01
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.152-b16 mixed mode):
"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000002ca2800 nid=0x3074 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" #12 prio=5 os_prio=0 tid=0x0000000018dc9800 nid=0x2980 waiting for monitor entry [0x0000000019a3f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.atguigu.jstack.ThreadDeadLock$2.run(ThreadDeadLock.java:63)
- waiting to lock <0x00000000d60b2630> (a java.lang.StringBuilder)
- locked <0x00000000d60b2678> (a java.lang.StringBuilder)
at java.lang.Thread.run(Thread.java:748)
"Thread-0" #11 prio=5 os_prio=0 tid=0x0000000018dc7000 nid=0x3b94 waiting for monitor entry [0x000000001993e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.atguigu.jstack.ThreadDeadLock$1.run(ThreadDeadLock.java:35)
- waiting to lock <0x00000000d60b2678> (a java.lang.StringBuilder)
- locked <0x00000000d60b2630> (a java.lang.StringBuilder)
"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000018cd6000 nid=0x3dc4 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000000018cd3000 nid=0x3048 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000000018c84000 nid=0x44bc waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000018c74000 nid=0x4080 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000018c71000 nid=0x47ac runnable [0x000000001933f000]
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 <0x00000000d6136878> (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 <0x00000000d6136878> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000178de800 nid=0x3488 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000018c38800 nid=0x29f8 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000178ba000 nid=0x41c0 in Object.wait() [0x0000000018c2e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5f08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000d5f08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000002d92000 nid=0xa64 in Object.wait() [0x0000000018b2f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5f06b68> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000d5f06b68> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"VM Thread" os_prio=2 tid=0x0000000017898000 nid=0x44fc runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002cb8000 nid=0x370c runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002cb9800 nid=0x2134 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002cbb800 nid=0x1184 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002cbd000 nid=0x4028 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x0000000018d5a000 nid=0x4750 waiting on condition
JNI global references: 30
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x0000000018dcfb28 (object 0x00000000d60b2630, a java.lang.StringBuilder),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x0000000018dd5338 (object 0x00000000d60b2678, a java.lang.StringBuilder),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.atguigu.jstack.ThreadDeadLock$2.run(ThreadDeadLock.java:63)
- waiting to lock <0x00000000d60b2630> (a java.lang.StringBuilder)
- locked <0x00000000d60b2678> (a java.lang.StringBuilder)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.atguigu.jstack.ThreadDeadLock$1.run(ThreadDeadLock.java:35)
- waiting to lock <0x00000000d60b2678> (a java.lang.StringBuilder)
- locked <0x00000000d60b2630> (a java.lang.StringBuilder)
Found 1 deadlock.
如果程序中出现死锁问题,jstack就会提示我们,并指出代码行数。
public class TreadSleepTest {
public static void main(String[] args) {
System.out.println("hello - 1");
try {
Thread.sleep(1000 * 60 * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello - 2");
}
}
同样用jstack分析;
参数
补充
其实我们也可以自己在代码中追踪线程的路径,用代码进行监控线程
public class TreadSleepTest {
public static void main(String[] args) {
System.out.println("hello - 1");
try {
Thread.sleep(1000 * 60 * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello - 2");
}
}
package com.atguigu.jstack;
import java.util.Map;
import java.util.Set;
/**
* 演示线程的死锁问题
*
* @author shkstart
* @create 下午 3:20
*/
public class ThreadDeadLock {
public static void main(String[] args) {
StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();
new Thread(){
@Override
public void run() {
synchronized (s1){
s1.append("a");
s2.append("1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2){
s1.append("b");
s2.append("2");
System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (s2){
s1.append("c");
s2.append("3");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1){
s1.append("d");
s2.append("4");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(new Runnable() {
@Override
public void run() {
Map<Thread, StackTraceElement[]> all = Thread.getAllStackTraces();//追踪当前进程中的所有的线程
Set<Map.Entry<Thread, StackTraceElement[]>> entries = all.entrySet();
for(Map.Entry<Thread, StackTraceElement[]> en : entries){
Thread t = en.getKey();
StackTraceElement[] v = en.getValue();
System.out.println("【Thread name is :" + t.getName() + "】");
for(StackTraceElement s : v){
System.out.println("\t" + s.toString());
}
}
}
}).start();
}
}
"C:\Program Files\JAVA\jdk1.8.0_152\bin\java.exe" "-javaagent:D:\BaiduNetdiskDownload\IntelliJ IDEA 2018.2.2\lib\idea_rt.jar=60020:D:\BaiduNetdiskDownload\IntelliJ IDEA 2018.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\charsets.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\deploy.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\access-bridge-64.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\cldrdata.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\dnsns.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\jaccess.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\jfxrt.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\localedata.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\nashorn.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunec.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunjce_provider.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunmscapi.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\sunpkcs11.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\ext\zipfs.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\javaws.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jce.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jfr.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jfxswt.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\jsse.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\management-agent.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\plugin.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\resources.jar;C:\Program Files\JAVA\jdk1.8.0_152\jre\lib\rt.jar;D:\idea\JVMDemo2\out\production\chapter02" com.atguigu.jstack.ThreadDeadLock
【Thread name is :Thread-2】
java.lang.Thread.dumpThreads(Native Method)
java.lang.Thread.getAllStackTraces(Thread.java:1610)
com.atguigu.jstack.ThreadDeadLock$3.run(ThreadDeadLock.java:82)
java.lang.Thread.run(Thread.java:748)
【Thread name is :Monitor Ctrl-Break】
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
java.net.SocketInputStream.read(SocketInputStream.java:171)
java.net.SocketInputStream.read(SocketInputStream.java:141)
sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
java.io.InputStreamReader.read(InputStreamReader.java:184)
java.io.BufferedReader.fill(BufferedReader.java:161)
java.io.BufferedReader.readLine(BufferedReader.java:324)
java.io.BufferedReader.readLine(BufferedReader.java:389)
com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
【Thread name is :Attach Listener】
【Thread name is :DestroyJavaVM】
【Thread name is :Thread-0】
com.atguigu.jstack.ThreadDeadLock$1.run(ThreadDeadLock.java:35)
【Thread name is :Finalizer】
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
【Thread name is :Reference Handler】
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.ref.Reference.tryHandlePending(Reference.java:191)
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
【Thread name is :Signal Dispatcher】
【Thread name is :Thread-1】
com.atguigu.jstack.ThreadDeadLock$2.run(ThreadDeadLock.java:63)
java.lang.Thread.run(Thread.java:748)
08-jcmd:多功能命令行
基本情况
基本语法
-
jcmd -l : 列出所有的JVM进程
-
jcmd 进程号 help:针对指定的进程,列出支持的所有具体命令
-
jcmd 进程号 具体命令:显示指定进程的指令命令的数据
-
根据以上命令来替换之前的那些操作:
Thread.print 可以替换 jstack指令
GC.class_histogram 可以替换 jmap中的-histo操作
GC.heap_dump 可以替换 jmap中的-dump操作
GC.run 可以查看GC的执行情况
VM.uptime 可以查看程序的总执行时间,可以替换jstat指令中的-t操作
VM.system_properties 可以替换 jinfo -sysprops 进程id
VM.flags 可以获取JVM的配置参数信息