低调不失奢华,“Java性能调优六大工具”之VisualVM多合一工具

VisualVM多合一工具

VisualVM是一个功能强大的多合一故障诊断和性能监控的可视化工具。它集成了多种性能统计工具的功能,使用VisualVM可以代替jstat、jmap、jhat、jstack甚至是JConsole。在JDK6update7以后,VisualVM便作为JDK的一部分被发布出来,它完全免费。

VisualVM也可以作为独立的软件进行安装,读者可以在http://visualvm.java.net上下载并安装VisualVM的最新版本。

在本节的介绍中,笔者所使用的VisualVM事先安装了一些必要的插件,为了保持功能上的一致,读者也可以安装图6.34所示的插件。

VisualVM插件的安装非常容易。既可以通过离线下载插件文件*.nbm,然后在Plugin对话框的Downloaded选项卡中,添加已下载的插件,如图6.35所示;也可以在AvailablePlugin选项卡中在线安装插件。

一,VisualVM连接应用程序

VisualVM支持多种方式连接应用程序,最常用的就是本地连接。只要本地计算机内有Java应用程序正在执行,在VisualVM的Local节点下就会出现这些应用。

双击应用或者右击应用,选择Open命令,就能够监控应用程序的运行情况,如图6.36所示。由于VisualVM本身也是Java应用程序,因此其自身也在列表内。

除了本地连接外,VisualVM也支持远程JMX连接。Java应用程序可以通过以下参数打开JMX端口:

可以选择如图6.37所示的命令来添加JMX连接。

然后在弹出的对话框中输入远程计算机地址、端口,如图6.38所示。如果需要验证,则再输入用户名和密码。

添加成功后,在Local节点下就会出现一个带有JMX图标的应用程序,如图6.39所示。图中的两个应用程序分别通过本地方式与JMX方式进行连接,两者的标识图标是不同的。

VisualVM还支持添加远程主机。远程主机可以通过jstatd工具建立,如使用以下命令开启jstatd服务器:

接着在VisualVM中添加远程主机,如图6.40所示。然后在Hostname(主机名)文本框中输入正确的计算机名称或者IP地址。连接成功后,在Remote节点下即可显示远程计算机上的Java应用程序,如图6.41所示。

二,监控应用程序概况

通过VisualVM,可以查看应用程序的基本情况,例如进程ID、MainClass、启动参数等,如图6.42所示。

单击Tab页面上的Monitor页面(图中未显示),即可监控应用程序CPU、堆、永久区、类加载和线程数的总体情况,如图6.43所示。通过单击页面上的PerformGC和HeapDump按钮,还可以手工执行FullGC操作和生成堆快照。

注意:VisualVM将CPU使用率、堆信息、永久区信息、线程及类加载情况作了图形化的展示,方便开发人员查看。

三,ThreadDump和分析

VisualVM的Thread页面(如图6.44所示)可以提供详细的线程信息。单击ThreadDump按钮可以导出当前所有线程的堆栈信息。在左下角的Threadsinspector区域,选中相应的线程也可以只导出选中线程的堆栈信息。

注意:VisualVM的Thread页面提供了详细的线程信息。该页面还会进行自动死锁监测,一旦发现存在死锁现象,便会提示用户。

四,性能分析

VisualVM有两个采样器。在Sampler页面下显示了CPU和内存两个性能采样器,用于实时地监控程序信息。CPU采样器可以将CPU占用时间定位到方法,内存采样器可以查看当前程序的堆信息。

下例是一个模拟函数频繁调用的Java程序。getNameById()为底层函数,被getNames-ByIds()和getNamesByIdsBad()函数频繁调用。

通过VisualVM的采样功能,可以找到该程序中占用CPU时间最长的函数,如图6.46所示。可以看到getNameById()函数占用了大量的CPU时间。

注意:VisualVM虽然可以统计函数调用的时间,但是无法给出函数调用堆栈。因此,通过VisualVM还是无法确定一个函数被谁调用了多少次。

在VisualVM的默认统计信息中,并不包含JDK的内置对象的函数调用统计,例如java.*包中的类。如果需要统计JDK内的函数调用情况,需要选中右上角的Settings复选框手工进行配置。图6.47增加了对java.lang.String的函数调用统计信息。

通过内存采样器,可以实时查看系统中实例的分布情况,如图6.48所示。随着程序的运行,VisualVM会实时更新这些数据,动态显示各个类所占用的内存大小。

五,快照

VisualVM可以保存某一个时刻应用程序的瞬时运行情况,包括程序的堆信息、线程堆栈等。通过图6.49所示的操作,可以保存当前应用程序的整体快照信息。保存后的快照可以另存为文件,以供日后分析使用,如图6.50所示。

六,内存快照分析

通过右击图6.51中选中的项,在弹出的快捷菜单中选择HeapDump命令,可以立即获得当前应用程序的内存快照。

内存快照分析功能如图6.52所示,在顶部的Tab页中提供了4个基本功能页:Summary、Classes、Instances和OQLConsole(OQL控制台)。下面分别介绍它们。

(1)Summary页面展示当前内存的整体信息,包括内存大小、实例总数、类总数等。

(2)在Classes页面中,以类为索引,显示每个类的实例数占用空间。在Classes页面中还可以对两个不同的内存快照文件进行比较,这个功能可以帮助开发者快速分析同一应用程序在运行的不同时刻,内存数据产生的变化,如图6.52所示。

在Classes页面中,如果需要获取指定类的更多信息,可以右击该类,选择showinInstancesView命令进入该类的实例页面,如图6.53所示。

(3)Instances页面将显示指定类的所有实例。开发者可以查看当前内存中内存数据的实际内容。图6.54所示为查看String对象实例页面的部分内容。可以看到,系统中所有的String对象都被一一罗列出来,并且可以看到所有对象的具体数据。

在右下角的References页面可以查看系统中引用这个实例的对象,展示对象间的引用关系。

(4)OQL控制台(OQLConsole)提供了更为强大的对象查询功能。有关VisualVM的OQL支持,将在后续章节进行详细阐述。

注意:通过VisualVM提供的内存快照分析工具,可以查看堆快照内的类信息和对象信息。

七,MBean管理功能

VisualVM可以通过插件集成JConsole的MBean管理功能,图6.55所示为在VisualVM中使用MBean管理功能。

注意:VisualVM的MBean管理功能和JConsole是完全一致的。

八,TDA的使用

TDA是ThreadDumpAnalyzer的缩写,是一款线程快照分析工具。当使用jstack或者VisualVM等工具取得线程快照文件后,通过文本编辑器查看和分析线程快照文件是一件非常艰难的事情。而TDA的功能就在

于帮助开发者分析导出的线程快照。TDA可以在
http://java.net/projects/tda/上下载。

TDA可以作为一款单独的软件运行,也可以作为VisualVM的插件运行。当作为单独的软件运行时,只需要使用TDA打开线程快照文件即可。当作为VisualVM插件运行时,只要在VisualVM中导出当前线程快照,TDA就会自动启动并分析快照文件。TDA运行时的界面如图6.56所示。

由图6.56可以看到,TDA将文本信息进行了分析和整理,以树、表格的形式显示这些信息。通过TDA,可以方便地查看哪些线程持有哪些对象锁。通过Monitors节点,可以显示所有的锁信息,并查看持有该锁的线程。

注意:TDA实际上是一个文本分析工具,它将线程快照的文本信息经过整理和统计,以图形化的方式展现出来,方便开发人员进行数据分析。

九,BTrace简介

BTrace是一款非常有意思的工具,它可以在不停机的情况下,通过字节码注入,动态监控系统的运行情况。它可以跟踪指定的方法调用、构造函数调用和系统内存等信息。本节在参考BTrace用户手册的基础上,着眼于实际应用,选取较为实用的几个BTrace脚本,演示BTrace工具强大的功能。

在VisualVM中安装BTrace插件后,便可以针对Java应用程序执行BTrace脚本了。在Java应用程序的节点上右击,选择快捷菜单中的Traceapplication命令即可进入BTrace插件界面,如图6.57所示。

图6.57选择Traceapplication命令

BTrace界面主要分为上下两部分,上半部分为代码区,下半部分为输出结果。在代码区中完成BTrace脚本的编写,单击Start按钮即可将BTrace脚本注入选中的应用程序中;程序输出结果将在下半部分显示,如图6.58所示。

本节使用的目标测试程序如下,该程序周期性地进行文件读写操作。下文中,将使用BTrace对该程序进行监控。

1.监控指定函数耗时

使用BTrace脚本可以通过正则表达式,指定监控特定类的特定方法的耗时。以下代码将监控所有类中名为writeFile()的方法的执行时间。

以上脚本使用@OnMethod注解指定要监控的类和方法名称。它在方法开始运行时记录方法的起始执行时间,在方法返回时记录方法的终止时间,从而计算方法的运行耗时。将这段脚本注入样例目标程序,部分输出结果如下:

注意:通过BTrace脚本,可以监控指定的某一个方法的运行耗时。

2.取得任意行代码信息

通过BTrace脚本的@Location注解,可以指定程序运行到某一行代码时触发某种行为。下例显示了通过BTrace脚本,获取BTraceTest类第26行代码的信息(当目标程序运行到第26行时,触发BTrace脚本)。

以上脚本在目标程序运行到第26行时触发,并打印该行信息。该脚本的部分输出结果如下:

由脚本输出可以看到,BTrace正确识别了BTraceTest类的第26行代码,正处于readFile()函数的运行区间中。若将@Location中line的值设置为-1,则BTrace脚本将在每一行触发。

3.定时触发

BTrace脚本支持定时触发,可以周期性地执行某种行为,以获取系统信息。下例使用@OnTimer注解分别制定两个周期性任务,分别为每秒运行一次和每3s运行一次。

在脚本的第6行,指定一个每秒运行一次的任务,并打印虚拟机的启动时间。在第12行,指定一个每3s运行一次的任务,每次都将导出系统的线程快照。

注意:通过BTrace可以在当前应用程序中定时获取一些运行时的系统信息。

4.监控函数参数

BTrace可以在运行时,监控传递给指定类的指定方法的参数,以获取应用系统执行时的内部细节信息,帮助程序排错和调优。

以上脚本监控BTraceTest类的writeFile()方法,并在每次方法调用时输出系统传递给该方法的参数。程序的部分输出结果如下:

加粗部分即为writeFile()方法的接收参数。通过BTrace在不影响系统正常运行的情况下,捕获了所有指定方法的调用及传入参数。

注意:BTrace可以跟踪指定方法的传入参数,获取方法的参数值,这对于现场问题排查会很有帮助。

5.监控文件

通过对I/O函数的监控,BTrace还可以捕获系统的I/O情况。下例中,通过BTrace脚本对FileInputStream和FileOutputStream对象进行监控,输出程序在运行时通过FileInputStream和FileOutputStream读取和写入的文件。

脚本中截获了FileOutputStream和FileInputStream的构造函数,记录读写的文件名称并将其输出。部分输出结果如下:

注意:在本例中,BTrace通过截获FileOutputStream和FileInputStream构造函数的方式监控文件I/O操作。如果文件I/O没有通过这两个构造函数发起,那么就无法通过这个脚本获得相关文件信息。

本文给大家讲解的内容是Java性能调优六大工具:VisualVM多合一工具

  1. 下篇文章给大家讲解的内容是Java性能调优六大工具:MAT内存分析工具
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值