简介
这份白皮书主要解决如何在Java 应用程序的服务器端使用IBM Rational PurifyPlus的问题。
这些说明也许并不能完全满足每种可能的部署环境――例如一个托管并运行Java server端组件的Java应用服务器。另外,现在市场上也有很多种Java 应用服务器。这份白皮书展示了一种经过验证的有效方法来使用Rational PurifyPlus测试运行在Apache Jakarta Tomcat Version 4 服务器上的 JSP(Java ServePages)和 Java Servlet应用程序。类似的方法可以应用在商业性的Java 应用服务器上;许多运行在BEA WebLogic(版本5.1、6.0、6.1)和IBM WebSphere( 版本3.5 和 4)的J2EE应用程序都因此得到了"净化"。
关于 Jakarta Tomcat
Jakarta是一个Sun公司支持的开源项目。它的最终目标是创造一个质量达到了那些商业解决方案要求的免费J2EE服务器端解决方案。Tomcat应用程序是整个项目的主要部分,并且在很多人看来,它几乎就等同于整个的 Jakarta 项目。Tomcat并不是一个完整的Java 应用服务器,它只是一个 Servlet+JSP 引擎,不过用它来部署和测试 JSP 和 Java Servlet 应用程序是绰绰有余的。它既可以独立运行,也可以集成在 Apache Web 服务器中运行。之所以选中 Tomcat 是因为它非常健壮、可靠,并可以免费获取。更多的关于Tomcat和Jakarta项目的信息可在文档末尾的参考文献列表中找到,在参考文献中列出的页面同时还包括一个到Tomcat安装程序和源代码的URL地址。
关于 IBM Rational PurifyPlus
PurifyPlus是一个测试Java应用程序的完整解决方案。它包括三个应用程序:
Rational Purify -- 一个内存分析工具(收集方法和对象层次的内存分析数据,并指出应用程序的内存热点所在)
Rational Quantify -- 一个应用程序执行时间分析工具(收集方法和线层次的分析数据并指出应用程序的性能瓶颈)
Rational PureCoverage -- 一个代码覆盖率分析工具(通过突出未执行的方法和代码行来收集没有测试到的部分的数据)
这三种工具不仅对Java,对Visual C/C++,Visual Basic和.Net应用也都提供了全面的支持。在这份白皮书中,Rational PurifyPlus指的是 Rational PurifyPlus 版本2001A。为了利用 Rational PurifyPlus来测试 Java Server端应用程序,您必须先在服务器上安装它。
关于 Servlets 和 JavaServePages
Servlets是运行在服务器端的 Java 应用程序;它们的主要作用是根据客户端的需要为Web页面创建内容。客户端通常是一个 Web 浏览器和一个用户用来输入数据的网页,这些数据将由运行在服务器端的Servlet处理。而 Servlet 处理的结果则将显示在客户端的网页上。
JavaServerPage(JSP) 基本上是一些 HTML 页面,它们带有一些特殊的标签可以用来将 Java代码包含进来或者访问服务器端运行的 Java beans 和servlet。Rational PurifyPlus并不能检查HTML语法,但它却可以通过监控从JVM(JAVA 虚拟机)上收集到的事件来测试JSP中包含的Java部分。
准备利用Rational PurifyPlus进行测试的Java servlets和JavaServer Pages
PurifyPlus提供了两种基本的数据收集级别: 方法级和行级。如果使用方法级来测试Java应用程序,您就不需要重编译测试的Java程序来获得所有和那些方法相关的数据。如果您对行级的信息感兴趣,那您就得用Symbolic调试信息来重编译Java代码。在Sun的Java编译器中用来得到Java类文件中的Symbols的开关是 '-g'。
>javac -g MyServlet.java
所有在兼容Sun Java2的虚拟机上运行的Java应用程序信息都可以通过JVMPI(Java Vitrul Machine Profiling Interface )收集。注意必须使用与Sun Java2 要求完全兼容的JAVA 虚拟机。Rational PurifyPlus 同时也完全支持 Microsoft Java 虚拟机。
在编译 servlet 时您需要在 CLASSPATH 中包含 servlet 库"servlet.jar"。整个库文件是随 Tomcat 一起安装的,可以在目录 /common/lib 中找到它。下面是一个使用 symbolic 调试信息来编译 MyServlet.java 的命令行示例:
Javac -g -classpath </common/lib/servlet.jar>
MyServlet.java
准备 Windows 环境以便利用 Rational PurifyPlus 测试 JSP 和 Java Servlets
环境变量:
JAVA_HOME
指明了默认 JVM 的 home 目录。它也是使用 Rational PurifyPlus 的JVM的默认选择。为了正确安装 Java 使得 PurifyPlus 可以运行,您必须在一个新的Java服务创建之后第一次profiling之前执行下面的命令行:
pstart -setup
这个命令会更新选中的Java实时环境(JRE:Java Runtime Enviroment)的Java Policy文件。现在来看另一个环境变量:
JAVA_OPTIONS(或者 IBM JVM 的 IBM_JAVA_OPTIONS )
Rational PurifyPlus 通过 Java 虚拟机假脱机接口(JVMPI)来收集所有关于Java应用程序的信息。因为JVM和Rational PurifyPlus是作为两个不同的进程运行的,Java进程需要载入一个名为PureJVMPI的PurifyPlus共享文件来侦听 JVM 事件,通过 JVMPI 收集运行数据。这个动态连接库是通过一个运行Java可执行文件时的附加选项:'-Xrun'来加载的。这里有一个关于PurifyPlus如何从命令行启动的例子:
>java -XrunPureJVMPI: Purify Java_App(或
>java -XrunPureJVMPI: Quantify Java_App(或
> java -XrunPureJVMPI: Coverage Java_App)
为了分析服务器端Java应用程序和服务,您需要手动创建一个特殊的包括"-Xrun"选项的系统参数,从而在每一次使用JAVA虚拟机时自动运行选中的PurifyPlus工具。对Sun JVM,整个变量的名称是_JAVA_OPTIONS,它的值应该是:
-XRunPureJVMPI: Purify (or -XrunPureJVMPI:Quantify or -XrunPureJVMPI:Coverage)
如果您使用的的是IBM JVM(在运行IBM WebSphere Java应用服务器时必须选择该JVM),那么整个环境变量的名字应该是 IBM_JAVA_OPTIONS.
在_JAVA_OPTIONS环境变量中设置的上述选项会使Tomcat应用程序运行时启动Rational Purify(或者Quantify和PureCoverage),而Purify(或者Quantify和PureCoverage)则会自动的开始收集该Java进程的数据。您可以使它的报告不包含与测试的JSPs和Servlets无关的数据,具体方式是通过预滤器(pre-filter)或PurifyPlus的过滤管理器来实现的。
准备Java 应用服务器环境来运行Rational PurifyPlus
为了使PurifyPlus和Java应用服务器一起运行,必须为服务器和PurifyPlus工具指定相同的JAVA_HOME 参数。对Apache Tomcat,您可以直接执行下列命令:
SET JAVA_HOME = < path to JRE installation directory>
如果是BEA WebLogic 服务器或者IBM WebSphere,可以修改您用来安装环境的批处理文件,只要根据如上所示改变参数JAVA_HOME的值就可以了。
准备PurifyPlus来收集在Apache Tomcat上运行的Java应用程序信息
为了使PurifyPlus可以收集在Apache Tomcat上运行的Java servlet或者JSP信息,您必须在开始测试之前创建一个自定义的预滤器(pre_filter)。
PurifyPlus过滤器。在PurifyPlus中有两种途径来过滤与测试无关的数据。第一种方法是为您要使用的工具(Rational PrufifyPlus、Quantify或PureCoverage)设定一个预滤器。
过滤器是一个列表,它包含了那些无需从中获取数据的Java包的名字。整个列表在Profile.ini文件的[Prefilter]节定义,您可以在PurifyPlus工具的主目录下找到该文件。
列表上的每个Java包都必须位于新行。请看一个演示预过滤在PurifyPlus中如何工作的例子:
图1: 一个Rational PurifyPlus 的 Profile.ini文件
假设我们想要过滤Java包com.sun 。如果我们将 "com.sun."(请注意这里字符串末尾的点号)作为一行放到Profile.ini的pre-filetering部分,那么这个文件和它的所有子包都将在PruifyPlus进行数据收集时被排除在外(请看图1)。如果要预过滤单个的类,您可以使用该类的全名(不需要结束的点号)。例如,com.rational.MyClass将预过滤com.rational包中的MyClass。如果您仅仅指明了类文件(e.g.MyClass),那么所有的包中的这个类都将被过滤掉。PurifyPlus不能过滤一个类的单个方法。
PurifyPlus过滤管理器。第二种方式是使用每一种工具的图形用户界面所提供的过滤管理器功能。过滤管理器为测试的Java应用程序创建一个特殊的二进制过滤文件(请看图2A和图2B)。它可以在profiling或者覆盖数据收集到之后使用。
图2A: Rational Quantify 中的PurifyPlus过滤管理器主窗口
在列表中选中的class文件将被排除在报告外,但从它们收集到的数据仍将保持在总的结果中。(也就是图2A中右下角的"Time"选择框)。
图2B. 使用 Rational PureCoverage中的 Rationgal PurifyPlus过滤管理器
为了在PurifyPlus中运行Tomcat,我为各个PurifyPlus工具(Purify、Quantify、PureCoverage )推荐下列的预过滤器列表:
org.omg.
javax.servlet.
com.sun.
org.apache.
org.xml
org.w3c.
sun.
对于其他Java服务器应用程序,您需要创建其他的预过滤器。请看我的技术贴士:http://www.therationaledge.com/content/sep_01/t_techTips_gb.html,它说明了如何在BEA WebLogic和IBM WebSphere的Java 应用服务器上运行Rational PurifyPlus。
演示应用程序
这篇文档用到的Demo程序是一个叫做"Duke's BookStore"的网上书店。这个Web应用程序可以在Sun的网站上下载。它原本是作为一个创建和运行Java servlet的指南的一部分而开发的。它包括一系列的Web页面以及为这些页面创建内容的servlet。Rational PurifyPlus可以用来测试这整个的Web应用程序或者它的一部分(比如说单个的servlet)。
在Rational PurifyPlus中对Java Serlets和JavaServerPages进行运行测试
在编译了Java组件并为工具设定了必要的过滤器之后,您可以开始从Java servlet和JSP中收集行层次的分析和代码覆盖信息了。
对于第一步,我建议使用Rational PurifyPlus并收集执行时间分析数据。
用Ratioanl Quantify 分析应用程序执行时间
将值"_XrenPureJVMPI: Quantify"赋给环境变量_JAVA_OPTIONS会在Tomcat服务器启动时激活Quantify。当你浏览演示程序时,Quantify会自动记录执行Web页上触发的方法和代码行所花费的时间。在Tomcat初始化并启动之后,可以在浏览器中输入如下的网址来访问演示程序:
http://localhost:8080/bookstore/bookstore.html
在测试结束之后,关闭浏览器并停止Tomcat服务器应用程序。分析的结果可以在Quantify中以几种不同的视图显示。第一种是CallGraph视图,如图3所示:
图3. Rational Quantify一个Web应用程序的CallGraph视图
CallGraph视图高亮显示了执行时消耗时间最多的调用链。粗体线条突出了应用程序中最慢的部分并表示了执行高亮显示的方法时所耗费的时间在总运行时间中的百分比。
行层次的信息在所选方法的注释源视图(Annotated Source View)中包含,如图4所示:
图4: Rational Quantify 中Web应用程序中一个方法的注释源视图
更进一步的信息可以通过Quantify创建的其他视图得到,包括图5所示的函数细节视图(Function Detail view)。
图5. Web应用程序中一个方法的 Rational Quantify 函数细节视图
Quantify相对于其他一些传统的解决方案的优势在于它表达分析性数据的方式。Quantify可以使您直接发现所测试应用程序的性能瓶颈的关键所在。
使用Rational PureCoverage进行代码覆盖
如果我们将_JAVA_OPTIONS环境变量改为"-XrunPrueJVMPI:Coverage"并重复对样例Web应用程序的运行测试,PureCoverage就会记录那些测试到的方法和代码行,并高亮显示那些没有被测试到的部分。
如图6A和图6B所示,PureCoverage提供了关于所测试的Java servlets应用程序的method和line两种级别的信息。
图6A. Rational PureCoverage 对一个测试Web应用程序的方法覆盖
在方法级覆盖中,PureCoverage根据该方法所在的模块或定义它的源文件来分类并提供被测试的应用程序的方法的相关统计数据。
关于被测试的应用程序的代码行的信息显示在加注的源代码中;不同的颜色分别表示代码选中,丢失,废弃或部分选中。
图6B. 测试的Web应用程序的一个servlet方法的 Rational PureCoverage line 级覆盖
这类信息在设定运行时间测试的步骤或创建自动测试的脚本文件时非常有用。PureCoverage 同时也允许您合并对同一个应用程序历次测试的覆盖数据,从而提供对应用程序所实施的测试的质量的一个清晰的概观。
利用Rational Purify进行内存分析
使用Rational Purify来获取对所测试的Web应用程序的内存分析大体上类似于使用PureCoverage和Quantify。对运行中的应用程序进行内存使用情况的"快照"可以让您在运行的不同阶段对内存状态进行比较。这是检测内存泄漏的一个很有用的方法。
服务器应用程序(常常是全天候运行)的内存泄漏能很容易的使应用程序和系统同时崩溃,因为在运行过程中它会不断地消耗越来越多的内存。内存泄漏对应用程序性能的影响也是巨大的。通过Rational Purify记录的Java应用程序的内存状态可以使您更深入地分析内存的使用状况。
Purify在对Java Servlet和JSP进行测试时提供的报告类型和它在测试Java 应用程序与Java applets时是一样的。图7显示了一个Purify记录一个接受测试的JSP如何调用JavaBean 方法。
图7: Demo JSP的 Rational Purify Call Graph
如图8中所示,在方法列表中提供了更多有关JSP 会话的内存使用信息。
图8. JSP的 Rational Purify 函数列表
与Rational Purify引导用户发现应用程序中消耗最多执行时间的部分类似,Purify向用户指出了应用程序的内存瓶颈所在。通过对函数列表视图中的方法进行排序可以很容易找到那些消耗了过多内存的方法;Purify同时还提供了很多其他视图来帮助您做到这一点。
用最少的投入获得最大的产出
在服务器机器上部署Rational Quantfify来获得 Java 服务器侧应用程序的广泛分析和代码覆盖率的数据是非常轻松的。您不但可以将Rational PurifyPlus应用在商业性的Java server应用程序上,同时也可以在轻量级的免费Java Servlets和JSP引擎(比如Apache Tomcat)上使用它。