JVM实践(二)JVM监控及诊断

一、jps命令

打印正在运行时的java进程信息。(类似linux中的ps)

-l    打印模块名以及包名
-v    打印传递给JVM的参数
-m    打印传递给主类的参数

 

打印机状态监控开源代码 java监控打印机_Test

二、jstat命令

 打印目标 Java 进程的性能数据。 

格式: jstat   -[参数]  [java进程号]  [打印间隔] [最大打印次数]。其中java进程号可由前面jps命令获取。

 实例 :jstat -gc 13516  ,这样默认只打印一次。

打印机状态监控开源代码 java监控打印机_java_02

 jstat -gc 13516 2s 5 每隔两秒打印一次,最多打印5次。

打印机状态监控开源代码 java监控打印机_java_03

常用分析命令参数

 

jstat -gc 13516     只打印一次
jstat -gc 13516 2s 5  每隔2秒打印一次,最大次数5。(不填就一直打印)
jstat -gc -t 13516 2s 5   -t可显示该进程存在了多久。

结果分析

名词解释:

S-Survivor存活区
C-Capacity容量
U-Utility已使用量
T-total 总量

E-eden 伊甸区
O-old 老年区

--------------结果列表各个参数含义-----------------
S0C、S1C 表示两个Survivor容量。
S0U、S1U 表示两个Survivor已使用量。
EC、EU   伊甸区容量和已使用量。
OC、OU   老年区容量和已使用量。

PC       perm内存容量,永久代
PU
MC       metaspace(元空间)的容量 
MU       元空间已使用量
CCSC     当前压缩类空间大小
CCSU     当前压缩类空间已使用大小
YGC      YOUNG GC次数 【伊甸区空间不足,就会进行一次年轻代回收,出现频率高】
YGCT     YGC总时间
FGC      FGC次数    【老年代内存不足触发,一般程序不会触发这个。触发这个基本程序要溢出异常。】
FGCT     FULL GC总时间 
GCT      GC总时间 【超过20%,堆的压力较大;超过 90%,快满了,随时都可能溢出。】

Java 虚拟机决定在使用 G1 GC 时,将所有 Survivor 内存区域的总容量以及已使用量存放至 S1C 和 S1U 中,而 S0C 和 S0U 则被设置为0.

打印机状态监控开源代码 java监控打印机_java_04

三、jinfo命令

查看传递给JVM的参数。

jinfo  [进程号]

jinfo –flag UseSerialGC 进程 可以指定其使用的GC策略。

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

查看元空间初始大小:

java -XX:+PrintFlagsInitial|grep MetaspaceSize

四、jstack命令

打印目标 Java 进程中各个线程的栈轨迹,以及这些线程所持有的锁。

jstatck [进程号]

如果出现死锁,出现信息:Found 1 deadlock.

出现死锁代码如下:

public class Test {
    public static Integer x = 1;
    public static Integer y = 2;
    public static void main(String[] args){
        Thread a = new Thread(new Test1());
        Thread b = new Thread(new Test2());
        a.start();
        b.start();
    }    
}
class Test1 implements Runnable{
    @Override
    public void run(){
        try{
            System.out.println("this is Test1");
            while(true){
                synchronized(Test.x){
                    System.out.println("this is Test.x");
                    Thread.sleep(5000);//等待Test进入y
                    synchronized(Test.y){
                        System.out.println("this is Test.y");
                    }
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
class Test2 implements Runnable{
    @Override
    public void run(){
        try{
            System.out.println("Lock2 running");
            while(true){
                synchronized(Test.y){
                    System.out.println("this is Test.y");
                    Thread.sleep(5000);
                    synchronized(Test.x){
                        System.out.println("this is Test.x");
                    }
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

检测出简单的死锁代码并打印出来: 

打印机状态监控开源代码 java监控打印机_java_05

五、GC日志查看

java启动参数中加入一些参数,可以打印GC日志
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-Xloggc:./gc.log 日志文件的输出路径
-XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:./gc.log

六、jmap命令

 查看堆内存细节。

jmap -heap [进程号]   查看堆内存分配情况。

打印机状态监控开源代码 java监控打印机_java_06

jmap -dump:format=b,file=e:\a\heap.hprof [进程号]   导出jvm内存信息(一般可以分析是否有大对象存活导致内存泄漏的潜在性)。

##查看JVM堆中对象详细占用情况
jmap -histo [进程号]

 

总结

  • jps查看Java进程号。
  • jstat 查看性能数据,GC情况。
  • jstack 查看线程状态/轨迹,还可以检测简单的死锁。
  • GC日志打印