VisualVM

随着JDK7而出现,位于JDK根目录下的bin目录下。运行环境需JDK1.6及以上,能监控JDK1.4以上版本的应用程序。

  • 相比JConsole,感觉功能更强大,且可集成各类插件,使其更强大。Jconsole算是VisualVM的子集吧。另外VisualVM也有JConsole的插件;
  • 相比Arthas,它最大的特点肯定就是图形化了。Arthas必须得命令敲着走,且命令众多,不易上手(还全是英文……),并且它是JDK自带的!
  • 对于eclipse和idea(VisualVM Launcher),也有相应插件,可在软件界面快速打开visualvm。

对于性能分析,主要几个点即是:

  • 监控:实时CPU监控内存监控线程监控、其他监控;
  • 转储:从内存中获得当前状态数据并存储到文件用于后续分析,一般是线程信息转储、类加载信息转储,以及堆上对象的转储
  • 快照:cpu情况快照内存情况快照
  • 分析:程序中函数的调用关系运行时间内存分配及使用情况、载入的类、存在的对象信息等。

而VisualVM对这几个点做得都还是蛮不错的,下面进行一一说明。

转储和快照

而对于VisualVM,从界面上即可看到:

它支持线程转储、堆转储,并且支持在发生OOM时立即转储堆(Arthas没有做到这一点)。同时拥有应用程序快照,快照生成后可查看线程快照、cpu、内存、类等使用情况。

另外概述一栏,可方便地看到系统信息、JVM参数等,对于JVM参数调优这些,它用起来很友好!

线程转储

上图我们可以看到有一个“线程dump”,线程转储后,可看到各个线程当前时间正在做什么事情:

线程dump看到的是当前时刻线程的一个状态,可以看到线程是否在运行、多个线程是否在资源竞争;

多次dump进行对比可排查线程是否存在问题,如多次dump,发现某一个线程一直在调某个方法,则可说明该方法可能有些问题。

针对线程转储,也可使用jdk自带工具jstackjstack -l [pid] > thread.dump

线程dump中可看到几个参数:

  • LoopThreadPool 线程/池名字
  • prio 线程优先级,默认为5
  • tid jvm线程ID,Thread.getId()获取到的就是它
  • nid 真实操作系统线程id

那么,我们如何查cpu占用比较大的线程呢?

常规方法
  1. 查到java进程id(pid):

    1
    2
    3
    jps -m  //方法一,jps:jdk自带工具
    ps ef|grep java //方法二,Linux
    tasklist|findstr java //方法三,Windows
  2. 查看该进程下的所有线程id:

    1
    2
    top -Hp [pid]  //方法一,Linux
    Process Explorer工具直接找到进程下cpu占用比较大的线程 //方法二,Windows

后续还可根据线程id,去线程dump文件分析相应线程的信息
需要把线程id转换为十六进制,再去dump文件中查相应nid。

Visualvm

VisualVM的 抽样器 -> CPU -> 线程CPU时间 可直接看到

Arthas

thred top [n] 命令可直接看到前n个线程

堆转储

图中有一个“堆dump”,堆转储后,可看到jvm堆在当前时间的一个状态:

图中可清晰地看到哪些类对象占用内存比较大,并且参考线程dump,你也可以进行多次堆dump,然后进行堆转储比较。

VisualVM在堆转储上的优势:

  • 能可视化直观地看到哪些类对象占比比较大,并且支持排序;
  • 支持两个堆转储比较(见图右上角);
  • 支持过滤快速查找类名(见图左下角);
  • 支持OQL控制台查询;
  • 支持点击某个类,可直观地看到该类的所有实例信息:重要

快照

图中有一个“应用程序快照”,快照后,可看到当前时间cpu、内存、类、线程情况。

监控

对于监控,VisualVM的监视一栏,可实时可视化查看cpu、内存、类、线程情况: