给一个系统定位问题的时候,知识、经验是关键的基础,数据是依据,工具是运用知识处理数据的手段。这里的数据包括但是不限于异常堆栈、虚拟机运行日志、垃圾收集器、线程快照、堆转存储快照等。

四、虚拟机性能监控、故障处理工具

4.1、基础故障处理工具

JDK 的bin目录下面存储着java.exe,javac.exe两个命令行工具。除了编译和运行程序外,打包、部署、签名、调试、监控、运维等各个场景都可能会用到他们。

据软件可用性和授权的不同,可以把Jdk中的工具分为三类:(商业授权工具,主要是JMC(JAVA Mission Control)及它要使用到的JFR(Java Flight Recorder),JMC这个原本来自JRockit的运维监控工套件从JDK7就被集成到了OracleJdk中,JDK11之前无需单独下载,但是在商业环境中使用它则是要付费的) ,正式工具,还有实验性工具

在bin目录下,每个工具体积基本稳定在21KB左右,它们的真正功能代码实现是在JDK的工具类库中,JDK9之前,这些代码实现在jdk\lib\tools.jar中,jdk以及之后在jdk\jmods中实现。如果是JDK5,需要监控JVM,需要在程序启动的时候添加参数“-Dcom.sun.management.jmxremote”,开启JMX管理功能,否则大部分工具都是基于JMX,这样它们都将无法使用。如果是JDK6或者以上版本,JMX默认是开启的

4.2.1、jps:虚拟机进程状况工具

jps(JVM Process Status Tool),Jdk很多工具都参考了UNIX的命名方式,它的功能也和ps命令类似,可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class ,main()函数所做的类名称已经这些进程在本地虚拟机的唯一Id).这个工具虽然功能单一,但是它绝对是使用频率最高的JDK命令行工具,因为其他JDK工具大多数都需要输入它查询到的LVMID来确定监控的是哪一个虚拟机进程。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(PID Process Identifier)是一致的,使用windows的任务管理器或者UNIX的ps命令也可以查询到虚拟机进程的LVMID,但是如果同时启动多个虚拟机进程,无法根据进程名称定为时,那就必须依赖jdp命令显示主类的功能才能区分了。

jps 命令格式:jps [options] [hostid]

执行这段代码
public class JpsTest {public static void main(String[] args) throws InterruptedException {System.out.println("Hello World!");Thread.sleep(500000);}
}

通过cmd执行 jps -m ,就可以显示虚拟机进程启动时传递给主类main()函数的参数和main函数所在的类

jps 还可以通过RMI协议查询了开启RMI服务的远程虚拟机进程状态,参数hostid为RMI注册表中注册的主机名如何使用 jps+jstatd 访问远程服务器上的jvm进程

参数详解:

-q:只输出LVMID,省略主类的名称,-m输出虚拟机进程启动时传递给主类的main()函数参数

-l:输出主类的全名,如果执行的是jar包,则输出jar的路径, -v输出虚拟机进程启动时的JVM参数

4.2.1、jstat:虚拟机统计信息监视工具

jstat可以很方便地建立远程RMI服务器,jps可以通过jstat查看远程虚拟机的LVMID。jstat可以显示本地或者远程虚拟机进程中类加载,内存,垃圾收集,即时编译等运行时数据。jstat工具在纯文本状态下监视虚拟机状态的变化,在用户体验上没有JMC、VIsualVM等可视化工具直观。

4.2.3、jinfo:java配置信息工具

jinfo的作用是实时查看和调整虚拟机各项参数,使用jps -v可以查看虚拟机启动时显示指定的参数列表,jinfo可以查看未被显示指定的参数系统默认值。

比如说查询CMSinitatingOccupancyFraction参数值

4.2.4 jmap:Java内存映像工具

jmap 命令用于生产堆转储快照(heapdump或者dump文件),如果不适用jmap命令,想要获取dump文件,也可以添加虚拟机参数-XX:+HeapDumpOnOutOfMemoryError参数,可以让jvm在内存溢出之后生成dump文件,也可以使用【Ctrl】+【Break】键让虚拟机生成dump文件,又或者再linux系统上通过Kill -3获得。

jmap的作用不仅仅是为了获取dump,还可以查询finalize执行队列、java堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。

导出的dump日志可以通过jvisualvm进行分析

4.2.5 jhat:虚拟机dump日志分析工具

不推荐用jhat来分析dump日志,一般是通过VisualVM,还有Eclipse Memory Analyzer、IBM HeapAnalyzer等工具来分析。

4.2.6、jstack:java堆栈跟踪工具

jstack 命令用于生成虚拟机当前时刻的线程快照,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程出现死锁、死循环、请求外部资源导致长时间挂起等。

[root@localhost bin]# ./jstack -L 40139
Usage:jstack [-l] <pid>(to connect to running process)jstack -F [-m] [-l] <pid>(to connect to a hung process)jstack [-m] [-l] <executable> <core>(to connect to a core file)jstack [-m] [-l] [server_id@]<remote server IP or hostname>(to connect to a remote debug server)Options:-F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)-m  to print both java and native frames (mixed mode)-l  long listing. Prints additional information about locks-h or -help to print this help message
[root@localhost bin]# ./jstack -l 40139
2020-05-13 19:40:32
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.212-b10 mixed mode):"Attach Listener" #8 daemon prio=9 os_prio=0 tid=0x00007f6d30001000 nid=0x9d2d waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f6d580db000 nid=0x9cd3 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f6d580d8000 nid=0x9cd2 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f6d580d6000 nid=0x9cd1 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f6d580d4800 nid=0x9cd0 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f6d580a1800 nid=0x9ccf in Object.wait() [0x00007f6d5d861000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x00000000f1a08ed0> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)- locked <0x00000000f1a08ed0> (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=0 tid=0x00007f6d5809e800 nid=0x9cce in Object.wait() [0x00007f6d5d962000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x00000000f1a06bf8> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:502)at java.lang.ref.Reference.tryHandlePending(Reference.java:191)- locked <0x00000000f1a06bf8> (a java.lang.ref.Reference$Lock)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)Locked ownable synchronizers:- None"main" #1 prio=5 os_prio=0 tid=0x00007f6d58009800 nid=0x9ccc waiting on condition [0x00007f6d61297000]java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at erwan.jvm.JpsTest.main(JpsTest.java:10)Locked ownable synchronizers:- None"VM Thread" os_prio=0 tid=0x00007f6d58095000 nid=0x9ccd runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f6d580de000 nid=0x9cd4 waiting on condition JNI global references: 5

从上面可以看到  java.lang.Thread.State: TIMED_WAITING (sleeping)  ,是由于随眠导致的TIMED_WAITING

4.3、可视化故障处理工具

JDK除了附带大量的命令行工具外,还提供了几个功能集成度更高的可视化工具,包括JConsole、JHSDB、VisualVM、JMC四个。

4.3.1、JHSDB:基于服务性代理的调试工具

JHSDB,是JDK9的功能。整合了几乎所有前面提到的基础工具,它支持命令行模式,也支持图形模式,JHSDB是一款基于服务性代理实现的进程外调试工具,服务性代理是HotSpot虚拟机中一组用于映射Java虚拟机运行信息的、主要基于Java语言(含少量JNI)代码实现的API集合。通过服务性代理的API,可以在独立的java虚拟机进程里分析其他HotSpot虚拟机的内部数据,或者从HotSpot虚拟机进程内存中dump出来的快照还原出它的运行状态细节

4.3.2、JConsole:Java监视与管理控制台

JConsole是一款基于JMX的可视化监视、管理工具。它的主要功能是通过JMX的MBean(Managed Bean)对系统进行信息的收集和参数的动态调整。

JMX支持跨服务器的管理,通过远程进程功能来连接远程服务器。JMX支持跨服务器的管理jconsole链接远程springboot,查看JVM信息,进入JConsole,可以看到主界面包括"概述","内存","线程","类","VM摘要","MBean"六个页签。

1、内存监控

“内存”页签的作用相当于可视化的jstat命令,用于监视被收集器管理的虚拟机内存(被收集器直接管理的Java堆和被间接管理的方法区)的变化趋势。

// -Xms100m -Xmx100m -XX:UseSerialGC
public class OOMObjectTest {static class OOMObject {public byte[] placeholder = new byte[64 * 1024];}public static void fillheap(int num) throws InterruptedException {List<OOMObject>list=new ArrayList<OOMObject>();for(int i=0;i<num;i++){//稍作延时,令监视曲线的变化更加明显Thread.sleep(50);list.add(new OOMObject());}System.gc();}public static void main(String[] args) throws InterruptedException {fillheap(1000);while(true);}
}

上面代码的作用是以64kb/50ms的速度向java堆中填充数据,一共填充1000次,从下图中可以看到,曲线是一致以平滑上升的,在1000次循环后,运行了System.gc()后,虽然整个新生代Eden和Survivor被请客,但是老年代依然没变,说明这些对象都存活。

1)虚拟机只限制了Java堆100MB,但是没有用-Xmn参数指定新生代大小,但是可以通过图标C的EdenSpace的已提交,默认Eden:Survivor为8:1,所以可以推算出总的新生代空间为27328KB/80%=34160KB

2)空间未回收的原因是, 对象都存活。List<OOMObject>存活的原因是因为 fillheap()方法还未退出,如果在fillheap()方法后执行gc,就可以回收掉全部内存。

2、线程监控

“线程”页签相当于可视化的jstack,导致线程长时间停顿的主要原因有,等待外部资源(数据库连接,网络分析,设备资源等)、死循环、锁等待等。

package erwan.jvm;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;/*** Hello world!**/
public class ThreadWaitingTest {public static void createBusyThread() {Thread thread = new Thread(new Runnable() {public void run() {while (true);}}, "testBusyThread");thread.start();}public static void createLockThread(final Object lock){Thread thread=new Thread(new Runnable(){public void run() {synchronized(lock){try{lock.wait();}catch(InterruptedException e){System.out.println(e.getMessage());}}}},"testLockThread");thread.start();}public static void main(String[] args) throws InterruptedException, IOException {BufferedReader br=new BufferedReader(new InputStreamReader(System.in));br.readLine();createBusyThread();br.readLine();Object obj=new Object();createLockThread(obj);}
}

下图显示了main函数BufferReader.readBytes()方法正在等待System.in的输入,这个时候线程为Runnable状态,Runnable状态的线程仍然会被分配运行时间,但是readBytes()方法检查到流没有更新就会立即归还执行令牌给操作系统,这种等待只消耗很小的处理器资源。JConsole监视一会儿后 main函数的线程就会消失。

下图显示testBusyThread线程,testBusyThread一直在执行空循环,这个时候线程为Runnable状态,而且没有归还线程执行令牌的动作,所以会在空循环中耗尽操作系统为它分配的执行时间,直至线程切换为止,这种等待会消耗大量的处理器资源。

testLocakThread线程在等待lock对象的notify()或notifyAll()方法的出现,线程这个时候处于WAITING状态,在重新唤醒前不会被分配执行时间。

下面代码展示一段死锁等待,200线程去计算1+2,和2+1的值,理论上for循环可以省略,这两个线程也能导致死锁,不过那样的概率太小。需要尝试运行多次才能看到死锁的效果。造成死锁的根本原因是Integer.valueOf()方法出于减少对象创建次数和节省内存的考虑,会对数值为-128~127直接的Integer对象进行缓存,所以代码中尽管调用了200次Integer.ValueOf()方法,但是一共只返回了两个Integer对象。如果在某个线程的两个Synchronized快之间发生了一次线程切换,那就会出现线程A在等待线程B持有的Integer.valueOf(1),而线程B在等待线程A持有的Integer.valueOf(2),结果大家都执行不下去的情况。

public class SynAddRunnable implements Runnable {int a,b;public SynAddRunnable(int a,int b){this.a=a;this.b=b;}public void run() {synchronized(Integer.valueOf(a)){synchronized(Integer.valueOf(b)){System.out.println(a+b);}}}public static void main(String[] args) throws InterruptedException, IOException {for(int i=0;i<100;i++){new Thread(new SynAddRunnable(1, 2)).start();new Thread(new SynAddRunnable(2, 1)).start();}}
}

下图显示的很清楚45被阻塞(BLOCKED),在等待48拥有的锁。

4.3.3、VisualVM:多合-故障处理工具

VisualVm(All-in-One Java Troubleshooting Tool)是功能最强大的运行监视和故障处理程序之一,曾经很长一段时间内是Oracle官方主力发展的虚拟机故障处理工具。它除了能运行监视,故障处理外,还提供了性能分析等功能。它的很大一个优点是不需要被监视的程序基于特殊的Agent去运行,因为它的通用性很强,对于应用程序实际性能的影响也较小。

1、VisualVM兼容范围与插件安装

VisualVm基于NetBeans平台,所以一开始它就具备了通过插件扩展功能的能力,通过插件可以做到:

  • 显示虚拟机进程以及进程的配置、环境信息(jps、jinfo)
  • 监视应用程序的处理器、垃圾收集、堆、方法区以及线程信息(jstat、jstack)
  • dump以及分析堆转储快照(jmap、jhat)
  • 方法级的程序运行性能分析,找出调用最多、运行时间最长的方法
  • 离线程序快照,收集程序运行时配置、线程dump、内存dump等信息建立一个快照,可以将快照发送给开发者进行Bug反馈

visualVM没有加载任何插件,所以我们需要手工安装,visualVM的Profiler页签中,VisualVM提供了程序运行期间方法级的处理器执行执行分析以及内存分析,做Profiling肯定会对程序运行性能有比较大的影响,一般不在生产环境中使用这项功能,或者改用JMC来完成,JMC对应用影响非常小。

2、BTrace动态日志跟踪

BTrace的作用是在不中断目标程序运行的前提下,通过HotSpot虚拟机的Instrument功能(HotSpot虚拟机允许在不停止运行的情况下,更新已加载的类的代码)动态加入原本不存在的调试代码,BTrace的用途很广泛,打印调用堆栈,参数,返回值只是它最基础的使用形式,在它的网站上有使用BTrace进行性能监视、定位连接泄漏、内存泄漏、解决多线程竞争问题等使用案例。   阿里巴巴开源的诊断工具Arthas也通过Instrument实现了与BTrace类似的功能。

4.3.4 Java Mission Control:可持续在线的监控工具

JFR是一套内建在HotSpot虚拟机里面监控和基于事件的信息收集框架,与其他监控工具相比,Oracle特别强调它的“可持续在线”的特性。JFR在生产环境中对吞吐量的影响一般不会高于1%,而且JFR监控过程的开始、停止完全可动态,即不需要重启应用。JMC与虚拟机之间同样采取JMX协议进行通信,JMC一方面作为JMX控制台,显示来自虚拟机MBean提供的数据;另外一方面作为JFR的分析工具,展示来自JFR的数据。

连接好JMC后,每个进程都有Mbean和JFR两个数据源,MBEan与JConsole和VisualVM上取到的内容是一样的

启动JFR(飞行记录时),可以进行记录时间、垃圾收集器、编译器、方法采样、线程记录、异常记录、网络和文件I/O、事件记录等选项和频率设定。飞行记录包含以下几类信息:

  • 一般信息:关于虚拟机、操作系统和记录的一般信息
  • 内存:关于内存管理和垃圾收集的信息
  • 代码:关于方法、异常错误、编译和类加载的信息
  • I/O:关于文件和套接字输入、输出的信息
  • 系统:关于正在运行Java虚拟机的系统、进程和环境变量的信息。
  • 事件:关于记录中的事件类型的信息,可以根据线索和堆栈跟踪,按照日志或图形的格式查看。

HotSpot的MBean中一般有各个分代大小,收集次数,时间,占用率等数据,这些都属于结果类的信息,而JFR中还可以看到内存中这段时间分配了哪些对象、哪些在TLAB中(或外部)分配、分配速率和压力大小如何、分配归属线程、收集时对象分代晋升的情况等,这些就是属于“过程”类的信息。

JVM2-性能监控故障处理工具相关推荐

  1. 《深入理解Java虚拟机第3版》垃圾收集器与内存分配策略、虚拟机性能监控故障处理工具

    目录 往期博客:Java课堂篇3_初识JMM.常量池简单理解(字符串常量池.静态常量池.大整型常量池) 为什么要了解垃圾收集和内存分配? 如何判断对象已死? 引用计数算法 可达性分析算法 JDK1.2 ...

  2. JVM(三).虚拟机性能监控故障处理工具

    JVM (三).虚拟机性能监控&故障处理工具 1.概述 系统定位问题,需要工具来导出出现问题的数据:这里的数据有异常堆栈,虚拟机日志,垃圾回收日志,线程快照,堆快照文件:工具就很多就是虚拟机自 ...

  3. 推荐几个Linux命令行下性能监控小工具

    原文链接 在Linux中,CPU,内存等系统状态可以通过top命令查看,或者用图形界面的工具,如gnome-system-monitor.但是,有时候,想知道更详细的信息,比如说进程树之类的,网络具体 ...

  4. 一款好用的Linux系统服务器性能监控分析工具介绍

    软件性能测试过程中经常要对服务器性能指标(比如CPU.内存.磁盘IO及网络IO等等)进行监控以分析出软件在此服务器上的性能瓶颈以便进行后续的服务器调优及软件性能优化.下面为大家介绍一款小编认为比较好用 ...

  5. react性能监控根据工具_高性能React:3个新工具可加快您的应用程序

    react性能监控根据工具 by Ben Edelstein 通过本·爱德斯坦 高性能React:3个新工具可加快您的应用程序 (High Performance React: 3 New Tools ...

  6. 阿里开源性能测试神器,性能监控分析工具Arthas

    Arthas(阿尔萨斯)是Alibaba开源的Java诊断性能监控分析工具,它不需要做任何的参数配置,就可以直观的获取各种维度的性能数据.通过阅读官网的介绍,可以看到,当我们遇到以下类似问题而束手无策 ...

  7. 应用性能监控管理工具

    应用程序性能监控 Application Manager 的应用程序性能监控(APM Insight) 使应用程序开发人员和 DevOps 工程师能够了解应用程序性能,并帮助他们在问题影响最终用户之前 ...

  8. 重磅推荐西瓜视频App性能监控开源工具!

    相关阅读:还在用 Guava Cache?它才是 Java 本地缓存之王! 内存泄漏监控工具 Raphael 是西瓜视频基础技术团队开发的一款 native 内存泄漏监控工具,具有接入简单.监控范围广 ...

  9. 程序性能监控分析工具

    1. CPU性能分析 gprof 编译:在编译选项中添加  -pg 使用:运行可执行文件,结束后本地生成gmon.out文件 gmon.out的查看:通过如下命令,将gmon.out转换成可阅读的文本 ...

最新文章

  1. Java知识点:条件编译
  2. Linux读写执行(RWX)权限
  3. Hbase学习-一步一步慢慢来
  4. flutter AnimatedPositionedDirectional 使用解析
  5. linux下部署jdk+Tomcat
  6. 浅谈TCP/IP协议中TCP与UDP的区别
  7. python九九乘法表矩形_用Python实现九九乘法表
  8. python 淘宝滑块验证_2020年最新的过某宝滑块验证技术,Python大牛轻松搞定技术难题...
  9. GhostScript命令参数详解
  10. React的调和过程(Reconciliation)
  11. 北京市参加汽车摇号条件
  12. 贪婪的大脑:为何人类会无止境地寻求意义 目录
  13. flvplayer.swfnbsp;flv视频播放器…
  14. openmv和stm32串口通信完成二维码识别
  15. 冒泡排序动态示意【Scratch】
  16. 4G模块(BC76)
  17. python 用tkinter 做一个简易番茄钟
  18. LaTeX 写作的两个辅助工具:统计中文字数和关闭Acrobat中的PDF文档
  19. 华为S2700以及S5700系列交换机 配置(详细)
  20. AutoCAD_创建直线,圆弧,圆

热门文章

  1. 【文献阅读】Silhouette based View embeddings for Gait Recognit
  2. 机器学习 上网时长分析
  3. (原創) 如何自行在ThinkPad X61安裝Windows XP Professional SP3? (NB) (ThinkPad) (X61) (OS) (Windows)...
  4. Arcgis创建新色带
  5. 使用Eric构建使用Caffe应用程序
  6. PetShop的系统架构设计(转Bruce Zhang(wayfarer) )
  7. TSDB时序数据库时序数据压缩解压技术浅析
  8. 代理方式部署NER标注平台doccano
  9. MPLS多协议标签交换技术
  10. ubuntu 16.04 和 18.04 替换apt源为阿里源