--------------作用:帮助判断cpu占用率过高、死循环、死锁、内存泄露、内存溢出等等问题
目录
❀❀ 需要掌握 ❀❀:
■ jps 查看进程ID
命令:jps
■ jstat 实时查看java进程运行的数据情况,可以判断是否内存泄露或者内存溢出的情况
命令:jstat -gc 进程ID(pid号) 或者 jstat -gcutil 进程ID
■ jstack ,查看或导出 Java 应用程序中线程堆栈信息,可以判断cpu占用率过高、死循环、死锁的情况
命令:jstack -l 进程I
✿ 常识或需要储备知识在文章最后~
一、常用工具详情:
1、jps (JVM Process Status Tool)
2、jstat(JVM Statistics Monitoring Tool)
3、jstack (Stack Trace forJava)
✿ 常识或需要储备知识~
✿ 常用操作----进程ID的查看与消灭进程:
1,cmd查看所有进程:netstat -ano
2,查看特定端口号的进程[例如:8080]: netstat -ano|findstr 8080
3,杀死对应的PID号对应的线程:taskkill /f /pid PID号
❀❀ 需要掌握 ❀❀:■ jps 查看进程ID命令:jps■ jstat 实时查看java进程运行的数据情况,可以判断是否内存泄露或者内存溢出的情况命令:jstat -gc 进程ID(pid号) 或者 jstat -gcutil 进程ID■ jstack ,查看或导出 Java 应用程序中线程堆栈信息,可以判断cpu占用率过高、死循环、死锁的情况命令:jstack -l 进程I |
■ 列出当前运行的所有java进程的ID
1):疑惑- wins 不是有任务管理器可以查看所有的进程,为啥还要jps?
答:虽然windows任务管理器可以查看所有的进程,是因为当不止一个java进程时,使用win10的任务管理器,很难区分他们;而且win10的工具只能看到进程,看不到线程,所以需要其他工具
2):jps 测试案例:
package jps;
import java.io.IOException;
/**
* ❀掌握:使用 jps命令查看java进程的ID
* 命令:jps
* 直接输入jps (相当于 jps -V )
*
命令格式: jps[options][hostid]
第一个参数options [-mlvV]可以任意组合使用
第二个参数:hostid
主机或者是服务器的ip,如果不指定,就默认为当前的主机或者是服务器。
注意:如果需要查看其他机器上的jvm进程,需要在待查看机器上启动jstatd。
*
* jps +
* -q: 显示进程ID
* -m: 显示进程ID,主类名称,以及传入main方法的参数
* -l: 显示进程ID,主类全名【全限定名】
* -v: 显示进程ID,主类名称,以及传入jvm的参数
* -V: 显示进程ID,主类名称[❀]
* @author Huangyujun
*
*-Xmn8m 指定年轻代内存大小
*/
public class jpsDemo {
public static void main(String[] args) throws IOException {
System.out.println("jps");
System.in.read();
}
}
■ 打开终端查看:
■ 测试 jps -m 命令前需要先设置面方法传递参数:
----------【具体步骤】在自己书写的测试类,右键->Run as -> Run Configurations… ->
■ 查看虚拟机运行数据------类装载、内存、垃圾收集、JIT编译 -----内存泄露或者内存溢出的判断【使用命令之前需要给虚拟机设置参数】
---因为控制台输入gc日志的前提:配置一下jvm的参数
例如:-Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:SurvivorRatio=8 * -Xms20M 堆的初始容量 -Xmx20M 堆的最大容量 -Xmn10M 堆中年轻(新生)代的大小 * -XX:+UseSerialGC 指定垃圾收集器SerialGC(串型垃圾回收器) -XX:+PrintGCDetails 打印内存中GC的行为 -verbose:gc 显示GC的情况 * -XX:ServivorRatio=8 设置 New Generation新生代中的 Eden区与Servivor区比例是8:1 ❀ 命令: jstat -gc 进程ID 或者 jstat -gcutil 进程ID 判断是否内存泄露或者内存溢出 [这个需要懂点内存jvm收集机制]:可以看文章(里边有演示怎么判断)--或者那本经典的书《深入理解Java虚拟机》;文章:《奇怪的GC (Allocation Failure)日志 - 简书 (jianshu.io)》 |
■ 案例:
package jstat;
import java.io.IOException;
/**
* -gc 选项:垃圾收集的堆统计信息
S0C、S1C:幸存区容量 S0C:当前幸存者空间0容量(kB) S1C:当前生存空间1的容量(kB)
S0U、S1U:❀堆内存中幸存区使用的容量 S0U:幸存者空间0使用大小(kB) S1U:幸存者空间1使用大小(kB)
EC、EU:伊甸园容量 伊甸园使用的容量 EC:当前伊甸园空间容量(kB) EU:伊甸园空间使用大小(kB)
OC、OU:❀老年代容量、老年代使用的容量 OC:当前的老年代容量(kB) OU:老年代使用大小(kB)
方法区的使用情况:MC、MU:元空间容量、元空间使用的容量 MC:元空间容量(kB) MU:元空间使用大小(kB)
压缩类的情况:CCSC:压缩的类空间容量(kB) CCSU:使用的压缩类空间(kB)
● 垃圾回收:●
● YGC:新生代垃圾收集事件的数量
● YGCT:新生代垃圾回收时间
● FGC:完整GC事件的数量
● FGCT:完整的垃圾收集时间
● GCT:总垃圾收集时间
==================================================
jstat -gc 线程ID
jstat -gcutil 线程ID
■ gc 和 gcutil 区别:gc显示的是大小, gcutil 显示的是占比
===================================================
* @author Huangyujun
* -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:SurvivorRatio=8
* -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc
* -Xms20M 堆的初始容量 -Xmx20M 堆的最大容量 -Xmn10M 堆中年轻(新生)代的大小
* -XX:+UseSerialGC 指定垃圾收集器SerialGC(串型垃圾回收器) -XX:+PrintGCDetails 打印内存中GC的行为 -verbose:gc 显示GC的情况
* -XX:ServivorRatio=8 设置 New Generation新生代中的 Eden区与Servivor区比例是8:1
*/
public class gc_gcutil {
//前提:配置一下vm的参数[JVM 配置]
//GC(Allocation Failure)[DefNew: 7072k->(956k),0.0042301 secs...][Times:user=0.01 sys=0.00, real=0.01secs]...
public static void main(String[] args) throws IOException {
final int _1MB = 1024 * 1024;
byte[] b1 = new byte[2 * _1MB];
System.out.println("1...");
System.in.read();//阻塞程序,当控制台输入回车键后继续执行
byte[] b2 = new byte[2 * _1MB];
System.out.println("2...");
System.in.read();
byte[] b3 = new byte[2 * _1MB];
System.out.println("3...");
System.in.read();
byte[] a4= new byte[4*_1MB];
}
}
/**
-gcutil 选项: 垃圾收集统计信息
S0:幸存者空间0利用率占该空间当前容量的百分比
S1:幸存者空间1利用率占空间当前容量的百分比
E:Eden空间利用率占空间当前容量的百分比
O:老年代利用率占空间当前容量的百分比
M:元空间利用率占空间当前容量的百分比
CCS:压缩的类空间利用率,以百分比表示
YGC:新生代GC事件的数量
YGCT:新生代垃圾回收时间
FGC:完整GC事件的数量
FGCT:完整的垃圾收集时间
GCT:总垃圾收集时间
*/
■ 查看或导出 Java 应用程序中线程堆栈信息,可以判断cpu占用率过高、死循环、死锁的情况
❀ 命令:jstack -l 进程ID
1)cpu占用率过高:
1.使用Process Explorer工具,找到CPU占用率高的进程的id;
2.右击该进程,查看属性,在thread选项卡中,找到cpu占用率高的线程id
3.把线程id转换成16进制
4.使用jstack -l 查看进程的线程快照
5.在线程快照中找到指定的线程,并分析代码
----通过工具,知道那个线程占用率高,然后在eclipse或者idea找到该占用率高的线程,从而知道占用率高的代码位置。
图1:使用Process Explorer工具,找到CPU占用率高的进程的id;右击该进程,查看属性,在thread选项卡中,找到cpu占用率高的线程id
图2:把线程id转换成16进制
图3:使用jstack -l 查看进程的线程快照;在线程快照中找到指定的线程,并分析代码
■ 案例(代码):
package jstack;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* jstack应用
* @author Huangyujun
*/
public class jstackTest {
public static void main(String[] args) {
System.out.println("start");
// test1();
// test2();
test3();
System.out.println("end");
}
//死循环
public static void test1() {
while(true) {}
}
//等待控制台输入
public static void test2() {
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
//死锁【我醒来了,我的锁被你拿了,你睡了;你醒来了,你的锁被我拿了,我睡了-------我等你,你等我【等不到的人】】
public static void test3() {
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
new Thread(() -> {
try {
lock1.lock();
Thread.sleep(100);
lock2.lock();//需要加锁,但是加锁失败,锁被另外一个线程myThread2持有
} catch (Exception e) {
e.printStackTrace();
}
}, "myThread1").start();
new Thread(() -> {
try {
lock2.lock();
Thread.sleep(100);
lock1.lock();//通过lock1加锁,失败,等待锁的释放,按照提示说是被myThread1持有,观察发现:myThread1中:lock1.lock(); Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}, "myThread2").start();
}
}
//死循环
//等待控制台输入
//死锁
1、System.in.read(); //让程序阻塞
2、Terminal 终端(方便,推荐) 也可以用win10的cmd控制台【dos窗口】
3、控制台输入gc日志的前提:配置一下jvm的参数[JVM 配置]
4、dos命令和进程命令相关的:
■ 常识----dos命令: DOS命令,是操作系统的命令,是一种面向磁盘的操作命令,主要包括 目录操作类命令、磁盘操作类命令、文件操作类命令和其它命令。 |
✿ 常用操作----进程ID的查看与消灭进程:1,cmd查看所有进程:netstat -ano2,查看特定端口号的进程[例如:8080]: netstat -ano|findstr 80803,杀死对应的PID号对应的线程:taskkill /f /pid PID号 |