【51CTO独家译稿】令人意想不到的宝贝,其实往往已经早就在你眼前,只不过你没发现它。VisualVM就是这样的。每当我们升级JDK、打开IDE时,其实我们就用上了它所带来的新特性。至少,我自己是这样认为的。
我第一次获知VisualVM是在去年二月份Geertjan Wielenga所写的一篇文章里,那时它的第三版都已经发布了。可以说VisualVM是Java开发者最为重要的工具,但同时这也是最不为人知的秘密。在Java的运行效率仍然是个问题的情况下,正是它有效的解决了这个问题。(有关VisualVM的简介,可参考51CTO之前发布的Sun VisualVM项目 开源Java问题解决方案一文)
VisualVM简介
简单说来,VisualVM是一种集成了多个JDK命令行工具的可视化工具,它能为您提供强大的分析能力。所有这些都是免费的!它囊括的命令行工具包括jstat, JConsole, jstack, jmap 和 jinfo,这些工具与JDK的标准版本是一致的。
你可以使用VisualVM生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和CPU分析,同时它还支持在MBeans上进行浏览和操作。尽管VisualVM自身要在JDK6这个版本上运行,但是JDK1.4以上版本的程序它都能监控。
对于我来说,这些功能都是至关重要的。以前我一直在使用如YourKit这样的一些付费软件来检测我的应用软件,但现在我可以用VisualVM这样一个开源工具来实现同样的功能。更何况,有谁比能Sun公司更了解JVM呢?
如何获取VisualVM
VisualVM的一个最大好处就是,它已经在你的JDK bin目录里了,只要你使用的是JDK1.6 Update7之后的版本。点击一下jvisualvm.exe图标它就可以运行了。
你所需要做的只是点一下jvisualvm.exe,就能启动它。运行中的所有Java应用程序将显示在右边的导航栏。你会发现根本不需要在VisualVM 里亲自为你的应用程序注册,因为它们全都会自动显示出来。你甚至还可以在导航栏里查看到远程的应用程序。
显示为“未知进程”(pid为5392)的程序是Eclipse
使用VisualVM
VisualVM有很多令人眼前一亮的功能,它能使你:
◆监控应用程序的性能和内存占用情况
◆监控应用程序的线程
◆分析(Profile)应用程序性能和内存分配情况
◆进行线程转储(Thread Dump)或堆转储(Heap Dump)
◆分析核心转储(Core Dump)
◆保存快照以便脱机分析应用程序。
用VisualVM评估IDE
我很想用VisualVM 做点什么,于是我决定,用它来对目前最先进的三个IDE进行评测。为此我特意新安装了 NetBeans 6.5.1 (JavaSE only version) , Eclipse (for Java Developers) 和 IntelliJ IDEA (8.1.2).
测试如下:
◆在VisualVM 中运行内存分析器(Memory Profiler)
◆在IDE中创建一个新的项目
◆创建一个简单的类,这个类只有一个可以打印“Hello World"的main方法
◆保存内存分析结果
◆生成这个应用程序的堆转储(Heap Dump)
◆从VisualVM 的监视视图(Monitor View)里获取信息
◆重新启动IDE,使用CPU分析器(CPU Profiler),在IDE中执行相同的步骤
◆保存CPU分析器(CPU Profiler)的结果
我意识到,CPU和内存评测其实是可以同时进行的,但为了便于下文的解释,我特意将它们分别进行。
我用IntelliJ做测试时,发现只有用我自己的JDK才能启动它,而不能用它自带的。虽然我太不熟悉这个IDE,但我发现当我用JSDK创建新工程时,它必须解析JDK中的文件。
此外,请注意,这些IDE都是我刚刚才下载的默认版本,没有针对Java开发作什么优化处理。
#p#
堆转储
我发现要对软件进行全面对比时,最好的手段是进行堆转储(Heap Dump)。这在程序运行时,使用VisualVM可以让这项工作变得十分太简单,你随时都可以右键单击那个程序,然后选择 Heap Dump 就可以了。
在个领域我评测的两个指标是:字节总数和类(class)的总数
NetBeans:
◆总的字节数:31,576,772
◆总的类数:10,583
IntelliJ :
◆总的字节数:76,582,715
◆总的类数:14,368
Eclipse:
◆总的字节数:62,112,960
◆总的类数:11,428
很明显,NetBeans只用到了Eclipse的一半都不到,IntelliJ则用去了多得多。
而在监视视图(Monitor View)里看着这些程序运行特别有意思,在这里我只关注了线程中的本地类,Eclipse差不多达到了25K,IntelliJ大概27K,NetBeans则在20K以下。
#p#
内存和CPU评测(Profile)结果
我注意到,当我开始评测(profiling)时,类和方法中的指令执行总是要让我等上好一段时间。尤其是在IDE里,这段时间不算短,不过还算可以接受吧。
内存和CPU评测对这些IDE的意义不是很大。但进行这个分析所带来的一个方便之处就是:你很容易就可以找到程序哪个地方发生了内存泄漏。以下是对这几个IDE的评测结果。
在这些IDE的评测结果中,我们可以看到一些很有趣的几点。例如,NetBeans中用到了大量了byte[] ,而在Eclipse和IntelliJ中就明显少得多了。另外我们还可以看到char[]在所有IDE里均被大量使用了。
◆NetBeans:内存的19.6%
◆Eclipse:内存的31.6%
◆IntelliJ:内存的32.7%
通过CPU评测我们能看出程序的哪个地方耗时最多。在这方面,各个IDE分别把时间用在了不同的方法(method)上,这一点有很大的不同:
◆NetBeans大部分时间花费在org.openide.util.RequestProcessor $ Processor.run()- 58.1 %
◆Eclipse的时间花在java.lang.reflect.Method.invoke()- 约占45.5 %
◆IntelliJ在java.net.SocketInputStream.read()上耗费掉了38.7 %的时间
虽然这么一个横向对比不一定能够说明什么问题。但能够看到这些IDE在幕后不同的工作方式,也是一件很有趣的事情。
至此,我不得不认为VisualVM 让这项评测变得相当的简单。我只需要在这些IDE启动之前运行VisualVM,它就能自动发现并挂载随后启动的每个IDE实例,然后就可以在VisualVM里作评测了。
#p#
IDE集成
Java开发人员大多都是被IDE惯坏了的,一旦没有顺手的IDE可用就会无所适从。不过不用担心,当前流行的这些IDE都已经有了VisualVM插件,这样你就可以在你最喜欢的IDE里工作了,不用再跟命令行打交道了。
VisualVM在NetBeans里的集成很有意思,它其实已经是NetBeans默认的分析器了。在NetBeans中,它作为一个RCP程序,可以与其它的NetBeans模块一起进行更好地扩展。
Eclipse和 IntelliJ IDEA的集成包可以通过点击这里获取。MyEclipse 7.5也已经集成了VisualVM的插件。作为一个Eclipse开发者,我很感兴趣这是究竟怎么办到的,因为这个工具毕竟是在NetBeans平台基础之上构建的。
与Eclipse的集成
首先,你得下载VisualVM Launcher插件,将它解压到你的Eclipse主目录里。这样当你打开Run Configurations对话框时,就会看到程序启动器选项。默认的启动器是可以在偏好(Preferences)设置里修改的。
在我的设置里,我选择当使用启动器时让VisualVM Launcher运行,其它时候就使用Eclipse默认的程序Launcher。你可以针对你的应用、小程序或者是Eclipse项目修改这些设置。
然后你还得指定你所要采用的VisualVM 可执行文件和JDK的路径。
这样与Eclipse的集成就算完成了,它会自动启动一个VisualVM ,你就可以用了。以后可能会有更深度的集成 ,那样的话说不定我就直接可以在IDE里启用它去分析程序了。
扩展VisualVM
如果上面列举的这些功能还不能满足你的需要,那么你还可以编写自己的VisualVM插件。VisualVM提供了许多的API调用入口,如下图所示:
◆标签扩展(Tab extension)。默认情况下,VisualVM提供了像“Overview",Monitor,Threads这样的一些标签。你可以自己定制一些类似的标签。此外,这些标签自身也可以扩展,你可以为它们设置二级标签,还可以设置这些标签是对所有VisualVM数据源都可见,还是只针对一些特定的数据源类型。
◆二级标签扩展(Subtab extension)。在上面所说的这些标签里,你可以插入新的标签,当然,这是在标签被设置为可扩展的前提下。可扩展的标签有:"Overview"、"Monitor"、"Threads"、"Heap Dump"和"Host"。当你插入一个新的子标签时,你可以指定它与其它子标签的相对位置关系。子标签也可以设置是对所有VisualVM数据源都可见,还是只针对一些特定的数据源类型。
◆菜单扩展(Menu extension)。一个数据源以及它的子节点,都可以为它们的上下文菜单添加一个或若干个菜单。
◆应用类型扩展(Application type extension)。在默认情况下,除非提供了一个特定的插件,否则在VisualVM里可见的这些应用都是一样的,它们有着同样的图标和标签。在定义了一种应用类型之后,你可以为这种特定的应用再安装一个插件,这样做可以为不同的应用具有不同的图标(比较简单),也可以提供像绘图这样的额外功能。
◆数据源的扩展(Data source extension)。 “应用程序”的数据源只是VisualVM可以监管的一种数据源类型。另一种数据源类型是“主机”数据源,它可让你监控和管理本地的和远程的主机。如果VisualVM的默认配置不能满足你的需求,你可以创建新的数据源类型让它监管。
在VisualVM的官方网站上,有一个关于编写VisualVM插件的详细说明,这份说明浅显易懂,如果你以前有过在NetBeans或者Eclipse上有过开发插件的经历,那就更容易上手了。不仅如此,VisualVM的插件中心里已经有不少现成的插件可用,只需进入“工具”/“插件”就可以看到了。
VisualVM 简单易用(相信你已经会用它了),还具备可供扩展的平台,这些都必将使它成为开发者不可或缺的工具。让我印象非常深刻的是,它能够自动挂载运行中的程序,而不用开发者去做注册工作。在理论上,我们甚至还可以在完善和再次启动Java应用程序的时,让它一直在后台运行,这实在是太妙了。
JDK中还藏着一个宝贝,它的名字叫做VisualVM。赶快去下载运行,让它帮你找出程序中的所有不足吧。
【编辑推荐】