java基础教程虚拟机性能分析和故障解决工具【命令行(jps、jstat、jstack)】

简介: java基础教程虚拟机性能分析和故障解决工具【命令行(jps、jstat、jstack)】

java基础教程虚拟机性能分析和故障解决工具

--------------作用:帮助判断cpu占用率过高-->死循环、死锁、内存泄露、内存溢出等等问题。


 

需要掌握

 jps 查看进程ID

  命令:jps

jstat 实时查看java进程运行的数据情况,可以判断是否内存泄露或者内存溢出的情况

  命令:jstat -gc 进程IDpid号)  或者 jstat -gcutil 进程ID

jstack ,查看或导出 Java 应用程序中线程堆栈信息,可以判断cpu占用率过高、死循环、死锁的情况

  命令:jstack -l 进程ID

 

常识或需要储备知识在文章最后~

 

 

一、常用工具详情:

1、jps (JVM Process Status Tool)

列出当前运行的所有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();
    }
}


打开终端查看:

449.png


测试 jps -m 命令前需要先设置面方法传递参数:

----------【具体步骤】在自己书写的测试类,右键->Run as -> Run Configurations… ->


49.png


2、jstat(JVM Statistics Monitoring Tool)

查看虚拟机运行数据------类装载、内存、垃圾收集、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:总垃圾收集时间
*/


3、jstack (Stack Trace forJava)  

查看或导出 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


image.png


图2:把线程id转换成16进制


51.png


 图3:使用jstack -l 查看进程的线程快照;在线程快照中找到指定的线程,并分析代码


52.png


案例(代码):


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();
    } 
}


//死循环

53.png

//等待控制台输入


54.png


//死锁


image.png


常识或需要储备知识~

1、System.in.read(); //让程序阻塞

2、Terminal 终端(方便,推荐) 也可以用win10的cmd控制台【dos窗口】

3、控制台输入gc日志的前提:配置一下jvm的参数[JVM 配置]

4、dos命令和进程命令相关的:

■ 常识----dos命令:

DOS命令,是操作系统的命令,是一种面向磁盘的操作命令,主要包括 目录操作类命令、磁盘操作类命令、文件操作类命令和其它命令。

✿ 常用操作----进程ID的查看与消灭进程:

1,cmd查看所有进程:netstat -ano

2,查看特定端口号的进程[例如:8080]:netstat -ano|findstr 8080

3,杀死对应的PID号对应的线程:taskkill /f /pid PID号

 

 

 

 

目录
相关文章
|
2月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
23天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
23天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
23天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
9天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
10 0
|
2月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
73 2
|
2月前
|
存储 运维 虚拟化
虚拟化数据恢复——Hyper-V虚拟化故障导致虚拟机文件丢失的数据恢复案例
在Windows Server上部署的Hyper-V虚拟化环境中,因存储中虚拟机数据文件丢失导致服务瘫痪。北亚企安数据恢复工程师通过物理检测、操作系统及文件系统检测,确定为人为格式化造成,并通过镜像硬盘、重组RAID、分析并恢复文件索引项等步骤,成功恢复数据,最终在新Hyper-V环境中验证并迁移所有虚拟机,确保用户业务恢复正常运行。
|
2月前
|
Java 数据库连接 编译器
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
|
2月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
本系列教程笔记详细讲解了Kotlin语法,适合希望深入了解Kotlin的开发者。对于需要快速学习Kotlin的小伙伴,推荐查看“简洁”系列教程。本篇笔记重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android库开发建议以及相互调用时的注意事项。
26 3
|
2月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
22 3
下一篇
无影云桌面