原文转载
概述
开发大型 Java 应用程序的过程中难免遇到内存泄露、性能瓶颈等问题,比如文件、网络、数据库的连接未释放,未优化的算法等。随着应用程序的持续运行,可能会造成整个系统运行效率下降,严重的则会造成系统崩溃。为了找出程序中隐藏的这些问题,在项目开发后期往往会使用性能分析工具来对应用程序的性能进行分析和优化。
VisualVM 是一款免费的性能分析工具。它通过 jvmstat、JMX、SA(Serviceability Agent)以及 Attach API 等多种方式从程序运行时获得实时数据,从而进行动态的性能分析。同时,它能自动选择更快更轻量级的技术尽量减少性能分析对应用程序造成的影响,提高性能分析的精度。
本文将对 VisualVM 的主要功能逐一介绍并探讨如何利用获得的数据进行性能分析及调优。
背景知识
性能分析的主要方式
回页首
VisualVM 安装
VisualVM 是一个性能分析工具,自从 JDK 6 Update 7 以后已经作为 Oracle JDK 的一部分,位于 JDK 根目录的 bin 文件夹下。VisualVM 自身要在 JDK6 以上的版本上运行,但是它能够监控 JDK1.4 以上版本的应用程序。下面主要介绍如何安装 VisualVM 以及各种 VisualVM 上的插件。
安装 VisualVM
VisualVM 项目的官方网站目前提供英文版本和多语言支持版本下载。多语言版本主要支持英语、日语以及中文三种语言。如果下载安装多语言版本的 VisualVM,安装程序会依据操作系统的当前语言环境去安装相应 VisualVM 的语言版本。最新 VisualVM 版本主要支持的操作系统包括:Microsoft Windows (7, Vista, XP, Server)、Linux、Sun Solaris、Mac OS X、HP-UX 11i。本文以 Microsoft Windows XP 为安装环境并支持中文。
安装 VisualVM 上的插件
VisualVM 插件中心提供很多插件以供安装向 VisualVM 添加功能。可以通过 VisualVM 应用程序安装,或者从 VisualVM 插件中心手动下载插件,然后离线安装。另外,用户还可以通过下载插件分发文件 (.nbm 文件 ) 安装第三方插件为 VisualVM 添加功能。
从 VisualVM 插件中心安装插件安装步骤 :
根据 .nbm 文件安装第三方插件安装步骤 :
回页首
功能介绍
下面我们将介绍性能分析的几种常见方式以及如何使用 VisualVM 性能分析工具进行分析。
内存分析
VisualVM 通过检测 JVM 中加载的类和对象信息等帮助我们分析内存使用情况,我们可以通过 VisualVM 的监视标签和 Profiler 标签对应用程序进行内存分析。
在监视标签内,我们可以看到实时的应用程序内存堆以及永久保留区域的使用情况。
此外,我们也可以通过 Applications 窗口右击应用程序节点来启用“在出现 OOME 时生成堆 Dump”功能,当应用程序出现 OutOfMemory 例外时,VisualVM 将自动生成一个堆转储。
在 Profiler 标签,点击“内存”按钮将启动一个内存分析会话,等 VisualVM 收集和统计完相关性能数据信息,将会显示在性能分析结果。通过内存性能分析结果,我们可以查看哪些对象占用了较多的内存,存活的时间比较长等,以便做进一步的优化。
此外,我们可以通过性能分析结果下方的类名过滤器对分析结果进行过滤。
CPU 分析
VisualVM 能够监控应用程序在一段时间的 CPU 的使用情况,显示 CPU 的使用率、方法的执行效率和频率等相关数据帮助我们发现应用程序的性能瓶颈。我们可以通过 VisualVM 的监视标签和 Profiler 标签对应用程序进行 CPU 性能分析。
在监视标签内,我们可以查看 CPU 的使用率以及垃圾回收活动对性能的影响。过高的 CPU 使用率可能是由于我们的项目中存在低效的代码,可以通过 Profiler 标签的 CPU 性能分析功能进行详细的分析。如果垃圾回收活动过于频繁,占用了较高的 CPU 资源,可能是由内存不足或者是新生代和旧生代分配不合理导致的等。
在 Profiler 标签,点击“CPU”按钮启动一个 CPU 性能分析会话 ,VisualVM 会检测应用程序所有的被调用的方法。当进入一个方法时,线程会发出一个“method entry”的事件,当退出方法时同样会发出一个“method exit”的事件,这些事件都包含了时间戳。然后 VisualVM 会把每个被调用方法的总的执行时间和调用的次数按照运行时长展示出来。
此外,我们也可以通过性能分析结果下方的方法名过滤器对分析结果进行过滤。
线程分析
Java 语言能够很好的实现多线程应用程序。当我们对一个多线程应用程序进行调试或者开发后期做性能调优的时候,往往需要了解当前程序中所有线程的运行状态,是否有死锁、热锁等情况的发生,从而分析系统可能存在的问题。
在 VisualVM 的监视标签内,我们可以查看当前应用程序中所有活动线程和守护线程的数量等实时信息。
VisualVM 的线程标签提供了三种视图,默认会以时间线的方式展现。另外两种视图分别是表视图和详细信息视图。
时间线视图上方的工具栏提供了缩小,放大和自适应三个按钮,以及一个下拉框,我们可以选择将所有线程、活动线程或者完成的线程显示在视图中。
我们在详细信息视图中不但可以查看所有线程、活动线程和结束的线程的详细数据,而且也可以查看某个线程的详细情况。
回页首
快照功能
我们可以使用 VisualVM 的快照功能生成任意个性能分析快照并保存到本地来辅助我们进行性能分析。快照为捕获应用程序性能分析数据提供了一个很便捷的方式因为快照一旦生成可以在任何时候离线打开和查看,也可以相互传阅。
VisualVM 提供了两种类型的快照:
回页首
转储功能
线程转储的生成与分析
VisualVM 能够对正在运行的本地应用程序生成线程转储,把活动线程的堆栈踪迹打印出来,帮助我们有效了解线程运行的情况,诊断死锁、应用程序瘫痪等问题。
当 VisualVM 统计完应用程序内线程的相关数据,会把这些信息显示新的线程转储标签。
堆转储的生成与分析
VisualVM 能够生成堆转储,统计某一特定时刻 JVM 中的对象信息,帮助我们分析对象的引用关系、是否有内存泄漏情况的发生等。
当 VisualVM 统计完堆内对象数据后,会把堆转储信息显示在新的堆转储标签内,我们可以看到摘要、类、实例数等信息以及通过 OQL 控制台执行查询语句功能。
堆转储的摘要包括转储的文件大小、路径等基本信息,运行的系统环境信息,也可以显示所有的线程信息。
从类视图可以获得各个类的实例数和占用堆大小数,分析出内存空间的使用情况,找出内存的瓶颈,避免内存的过度使用。
通过实例数视图可以获得每个实例内部各成员变量的值以及该实例被引用的位置。首先需要在类视图选择需要查看实例的类。
此外,还能对两个堆转储文件进行比较。通过比较我们能够分析出两个时间点哪些对象被大量创建或销毁。
线程转储和堆转储均可以另存成文件,以便进行离线分析。
回页首
总结
本文首先简要列举了一些性能分析相关的背景知识。然后介绍了 VisualVM 的下载和安装。最后从内存性能、CPU 性能、快照功能以及转储功能四个方面展开,进一步说明了如何使用 VisualVM 进行性能分析。通过本文的介绍,相信读者对性能分析会有一定的了解,并可以利用 VisualVM 进行性能分析。
参考资料
学习
讨论
加入 developerWorks 中文社区。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。
转载地址:http://www.ibm.com/developerworks/cn/java/j-lo-visualvm/
使用Java自带的VisualVM监控远程主机JVM内存使用情况
下面是使用JXM协议配置的简单的操作步骤,详细内容可以阅读文章后的参考资料。
1.远程主机
(1)修改JMX服务的配置文件:
在JDK的根目录/jre/lib/management中,将jmxremote.password.template另存为jmxremote.password。
用文件编辑软件按编辑jmxremote.password去掉
# monitorRole QED
# controlRole R&D
前面的#注释,保存。
如果当前系统属于AIX、Linux或者Solaris系统还需要更改jmxremote.access和jmxremote.password的权限
为只读写,命令如下
chmod 600 jmxremote.access jmxremote.password
(2)修改JVM的启动配置信息:
Windows系统
set JAVA_OPTS=-Dcom.sun.management.jmxremote.port=<port> -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=<hostname>
-Dcom.sun.management.jmxremote.ssl=false
AIX、Linux或者Solaris
export JAVA_OPTS="-Dcom.sun.management.jmxremote.port=<port> -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=<hostname>
-Dcom.sun.management.jmxremote.ssl=false"
例如:
set JAVA_OPTS=-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.1.24
-Dcom.sun.management.jmxremote.ssl=false
配置的说明如下:
-Dcom.sun.management.jmxremote.port 远程主机端口号的
-Dcom.sun.management.jmxremote.ssl=false 是否使用SSL连接
-Dcom.sun.management.jmxremote.authenticate=false 是否开启远程服务权限
-Djava.rmi.server.hostname 远程主机名,使用IP地址
(3)重启服务。
2.本地主机配置
方法一、
进入<JDK_HOME>\bin目录,启动JConsole命令行工具。在JConsole的新连接中添加运程计算机信息。
<hostname>:<port>或者service:jmx:<protocol>:<sap>
例如:192.168.1.24:1099或者service:jmx:rmi:///jndi/rmi://192.168.1.24:1099
<hostname> 检测服务器IP地址
<port> 运程主机端口
方法二、
JDK 1.6以上版本包含了一个简单版本的jvisualvm.exe。在Remote上右键菜单中选择Add Remote host,输入运程计算机Host name,实际上就是要检测的远程计算机IP地址。在配置好的远程主机上右键选择Add JMX Connection...,按照方法一中要求的格式输入,远程主机信息。
参考:
[Java VisualVM 入门指南]
http://visualvm.java.net/zh_CN/gettingstarted.html
[Java VisualVM quickstart]
http://visualvm.java.net/api-quickstart.html
[Monitoring WASCE in JConsole][主要参考]
http://publib.boulder.ibm.com/wasce/V2.1.0/en/working-with-jconsole.html
[JDK中还藏着一个宝贝 它的名字叫做VisualVM]
http://developer.51cto.com/art/200906/130424.htm
[JVM内存监控:visualVM]
http://www.diybl.com/course/3_program/java/javajs/20100719/461823.html
sun 关于Java VisualVM的说明文档
http://download.oracle.com/javase/6/docs/technotes/guides/visualvm/intro.html
visualvm的下载地址如下:
下载地址:http://visualvm.java.net/