TPTP教程

Eclipse Test and Performance Tools Platform 简介
用一种高级的可扩展平台来测试、分析和监视应用程序

TPTP 简介

在交付健壮的产品质量的程序所需的过程中,编写应用程序或 servlet 的 Java 代码只是第一个阶段。必须对代码进行测试,检验它的操作和正确性。往往还必须对代码进行分析,以便消除性能瓶颈和资源浪费(尤其是内存)。还必须对代码进行监视,以便对故障进行定位、识别使用模式、寻找进一步增强和优化的机会以及探测入侵尝试和实际的入侵。

Eclipse TPTP 是什么?

虽然存在许多对代码进行测试、分析和监视的工具,但是很少能够集成为一个大型的工具包。另外,这类工具通常是由不同的厂商提供的,这使您不得不花费宝贵的时间和精力来学习和掌握许多不同的用户界面(UI)、编译器和诊断技术。在时间和资金两方面,专有的开发工具都需要很大的投资。

但是,如果测试工具、分析器和监视器是开放源码的,那么会怎么样?而且,如果这些工具是可扩展的,任何厂商或开发人员都可以创建新工具或者对现有工具进行改进,那么会怎么样?如果这些工具能够很好地集成到一种现有的流行的开发环境中,那么会怎么样?这恐怕是白日做梦吧?不,这已经是现实了。

Eclipse TPTP 是一种软件体系结构以及几个扩展了 Eclipse 平台的组件(到目前为止),它在 Eclipse 平台上提供了测试、性能和监视工具。一些 Java、C 和 C++ 开发人员使用 TPTP 为其他开发人员构建独特的工具,还有一些开发人员将 TPTP 提供的工具和 Eclipse 的其他特性组合起来,构建和部署供用户使用的应用程序。

TPTP 提供了什么

简单地说,TPTP 是一个 Eclipse Foundation 顶级项目,它的目标是:“构建一个通用的可扩展的基于标准的工具平台,软件开发人员可以在这个平台上创建专用的可互操作的...测试和性能工具。” 换句话说,TPTP 在本质上是一个工具,用来构建对软件质量控制进行自动化的工具。

实际上,TPTP 的当前版本包括核心工具和三种核心衍生工具:

TPTP
TPTP 为 UI 开发、数据收集、基于规则的数据查询以及应用程序的控制提供了基础代码。例如,TPTP 提供了其他工具可以重用和扩展的许多向导。它还提供了编程接口和一个守护进程,以便帮助从正在运行的本地或远程进程中收集数据。
TPTP Testing Tools
这个项目是在 TPTP 之上构建的,提供了对应用程序进行各种自动化测试所需的其他服务。当前版本支持 JUnit 自动测试、一种指向和点击脚本编程系统(用于进行手工测试并记录结果)和一个用于测试 Web 应用程序的自动化系统,包括一个可以记录和回放 Web 浏览会话并对结果进行验证的记录器。Eclipse V4.1 还包括一个图形用户界面(GUI)记录器的早期版本,它可以记录和回放基于 SWT 的界面中的鼠标和键盘事件。
TPTP Monitoring Tools
这个项目对来自日志文件或来自应用程序收集的统计数据的数据进行收集、分析和图形显示。
TPTP Tracing and Profiling Tools
这个项目也扩展了 TPTP,用来收集和分析正在运行的应用程序中的资源使用数据,包括 CPU 和内存。这个跟踪工具还允许与正在运行的进程进行交互。例如,可以手工地实施垃圾收集并检查剩余的对象池,从而寻找和修复内存 “泄漏”。
另外,TPTP 包括一个称为 Agent Controller 的守护进程。Agent Controller 是 Eclipse 工作台和被测试的应用程序之间的 “联络人”。它代表 Eclipse 启动本地或远程 Java 应用程序并转发应用程序度量(包括应用程序日志文件)给 Eclipse。

Eclipse Test and Performance Tools Platform 简介
用一种高级的可扩展平台来测试、分析和监视应用程序

级别: 中级
Martin Streicher, 主编, Linux Magazine
2006 年 3 月 23 日
学习如何使用 Eclipse Test and Performance Tools Platform(TPTP)分析 Java™ 应用程序,并研究如何测量内存使用量、识别内存泄漏并隔离性能瓶颈。
开始之前
在本教程中可以学到什么?如何从本教程获得最大的收益?
关于本教程
本教程介绍 Eclipse Test and Performance Tools Platform(TPTP),逐步说明了如何安装 Eclipse 和 TPTP 工具,并演示如何分析正在运行的 Java 应用程序。

前提条件
为了从本教程中获益,您应该具备 Java 软件开发经验并了解整个软件开发生命周期,包括测试和分析。还应该熟悉从命令行安装软件,以及设置和管理 shell 和系统环境变量,比如 Java CLASSPATH。了解 Eclipse 和 Standard Widget Toolkit(SWT)也是有帮助的。
在开始之前,必须在 UNIX®、Linux®、Mac OS X 或 Microsoft® Windows® 系统上安装几个软件包。需要 Java 虚拟机(Java Virtual Machine,JVM)、Eclipse 平台、Eclipse TPTP 运行时以及 TPTP 所依赖的几个软件。还需要 TPTP 的 Agent Controller,它允许启动并分析应用程序。下面是所需的所有软件:
•    Java 2 Platform, Standard Edition(J2SE) V1.4 Software Development Kit(SDK)
•    J2SE V1.4 Java Runtime Environment (J2RE)
•    Eclipse V3.1 SDK
•    Eclipse Modeling Framework(EMF) SDK V2.1
•    XML Schema Infoset Model(XSD) SDK V2.1
•    V1.1.1 of UML2
•    TPTP 运行时
•    Agent Controller 运行时 (适合您系统的版本)
•    Eclipse Update Manager(可选)

系统需求
如果系统上没有安装 JVM 和 Eclipse,那么所有软件至少需要 300 MB 的空闲磁盘空间。还需要有足够的空闲物理内存来运行 JVM。一般来说,建议使用 64 MB 或更多的空闲物理内存。
TPTP 简介
在交付健壮的产品质量的程序所需的过程中,编写应用程序或 servlet 的 Java 代码只是第一个阶段。必须对代码进行测试,检验它的操作和正确性。往往还必须对代码进行分析,以便消除性能瓶颈和资源浪费(尤其是内存)。还必须对代码进行监视,以便对故障进行定位、识别使用模式、寻找进一步增强和优化的机会以及探测入侵尝试和实际的入侵。
Eclipse TPTP 是什么?
虽然存在许多对代码进行测试、分析和监视的工具,但是很少能够集成为一个大型的工具包。另外,这类工具通常是由不同的厂商提供的,这使您不得不花费宝贵的时间和精力来学习和掌握许多不同的用户界面(UI)、编译器和诊断技术。在时间和资金两方面,专有的开发工具都需要很大的投资。
但是,如果测试工具、分析器和监视器是开放源码的,那么会怎么样?而且,如果这些工具是可扩展的,任何厂商或开发人员都可以创建新工具或者对现有工具进行改进,那么会怎么样?如果这些工具能够很好地集成到一种现有的流行的开发环境中,那么会怎么样?这恐怕是白日做梦吧?不,这已经是现实了。
Eclipse TPTP 是一种软件体系结构以及几个扩展了 Eclipse 平台的组件(到目前为止),它在 Eclipse 平台上提供了测试、性能和监视工具。一些 Java、C 和 C++ 开发人员使用 TPTP 为其他开发人员构建独特的工具,还有一些开发人员将 TPTP 提供的工具和 Eclipse 的其他特性组合起来,构建和部署供用户使用的应用程序。

TPTP 提供了什么
简单地说,TPTP 是一个 Eclipse Foundation 顶级项目,它的目标是:“构建一个通用的可扩展的基于标准的工具平台,软件开发人员可以在这个平台上创建专用的可互操作的...测试和性能工具。” 换句话说,TPTP 在本质上是一个工具,用来构建对软件质量控制进行自动化的工具。
实际上,TPTP 的当前版本包括核心工具和三种核心衍生工具:
TPTP
TPTP 为 UI 开发、数据收集、基于规则的数据查询以及应用程序的控制提供了基础代码。例如,TPTP 提供了其他工具可以重用和扩展的许多向导。它还提供了编程接口和一个守护进程,以便帮助从正在运行的本地或远程进程中收集数据。
TPTP Testing Tools
这个项目是在 TPTP 之上构建的,提供了对应用程序进行各种自动化测试所需的其他服务。当前版本支持 JUnit 自动测试、一种指向和点击脚本编程系统(用于进行手工测试并记录结果)和一个用于测试 Web 应用程序的自动化系统,包括一个可以记录和回放 Web 浏览会话并对结果进行验证的记录器。Eclipse V4.1 还包括一个图形用户界面(GUI)记录器的早期版本,它可以记录和回放基于 SWT 的界面中的鼠标和键盘事件。
TPTP Monitoring Tools
这个项目对来自日志文件或来自应用程序收集的统计数据的数据进行收集、分析和图形显示。
TPTP Tracing and Profiling Tools
这个项目也扩展了 TPTP,用来收集和分析正在运行的应用程序中的资源使用数据,包括 CPU 和内存。这个跟踪工具还允许与正在运行的进程进行交互。例如,可以手工地实施垃圾收集并检查剩余的对象池,从而寻找和修复内存 “泄漏”。
另外,TPTP 包括一个称为 Agent Controller 的守护进程。Agent Controller 是 Eclipse 工作台和被测试的应用程序之间的 “联络人”。它代表 Eclipse 启动本地或远程 Java 应用程序并转发应用程序度量(包括应用程序日志文件)给 Eclipse。
本教程的剩余部分演示针对 Java 技术的几种 TPTP 分析工具。
安装必需的软件和组件
在开始学习本教程之前,必须安装和设置 “前提条件” 小节中列出的软件和组件。

安装 J2SE 和 J2RE
下载并安装 J2SE V1.4 SDK 和 V1.4 J2RE。(如果系统上已经有 J2SE V1.4.2_10 或更高版本,那么可以跳过这一步。)

通常,J2SE SDK 和 Java Runtime Environment(JRE)是以自解压的二进制文件形式发布的。Linux 上的安装通常只需执行以下命令:

清单 1. J2SE SDK 和 Java Runtime Environment 安装


% cd ~
% mkdir ~/java
% cd ~/java
% mv ~/j2sdk-1_4_2_10-linux-i586.bin .
% mv ~/j2re-1_4_2_10-linux-i586.bin .
% chmod +x j2sdk-1_4_2_10-linux-i586.bin j2re-1_4_2_10-linux-i586.bin
% ./j2sdk-1_4_2_10-linux-i586.bin
.
% ./j2re-1_4_2_10-linux-i586.bin
.
% ls -F
j2re1.4.2_10/   j2sdk1.4.2_10/

使用 Eclipse Update Manager 安装 TPTP(可选)
如果已经安装了 Eclipse,那么可以使用 Eclipse Update Manager 安装 TPTP。步骤如下:
1.    点击 Help > Software Updates > Find and Install。
2.    选择 Search for new features to install 选项,然后点击 Next。
3.    点击 New Remote Site,然后分别输入 TPTP Update Site 和 http://eclipse.org/tptp/updates/site.xml 作为名称和 URL。点击 Finish。
4.    选择要安装的特性,然后点击 Next。
5.    接受许可协议,点击 Next,然后点击 Finish。
6.    在确认提示中,点击 Install All。当安装完成时,重新启动 Eclipse。
现在,可以跳过后面 “安装 Agent Controller” 小节中描述的安装 Agent Controller(它必须手工安装)的步骤。如果还没有安装 Eclipse,请继续阅读下文。

安装 Eclipse V3.1 SDK
下载适合自己平台的 Eclipse 3.1 SDK。可以在 Eclipse Downloads 上找到这个 SDK。通常,安装时只需将 Eclipse .tar.gz 文件释放到您选择的目录中。例如,如果使用 Linux,那么下载 Eclipse V3.1 SDK tarball,然后使用以下命令将它释放到一个目录中,比如 ~/java/:

% cd ~/java
% mv ~/eclipse-SDK-3.1.1-linux-gtk.tar.gz .
% tar zxvf eclipse-SDK-3.1.1-linux-gtk.tar.gz

如果想检验 Eclipse 是否已经成功安装了,那么留在释放 Eclipse 的目录中,确保 java 可执行文件在 PATH 中并运行 java -jar eclipse/startup.jar。例如:

清单 2. 检验 Eclipse 是否已经成功安装了


% export JAVA_DIR=$HOME/java
% export JAVA_HOME=$JAVA_DIR/j2sdk1.4.2_08/sdk
% export PATH=$JAVA_HOME/bin
% export CLASSPATH=$JAVA_HOME
% cd $JAVA_DIR
% java -jar eclipse/startup.jar

如果提示您为工作空间选择目录,那么输入 $HOME/java/workspace。这个目录将保存您在 Eclipse 中创建的所有项目。(当然,如果有许多项目,以后可以选择其他目录,让一个工作空间只包含一个项目。)

安装 EMF SDK V2.1
如果 Eclipse 正在运行,就退出它并下载 EMF SDK V2.1。(根据 EMF Web 站点所说,“EMF 是一种建模框架和代码生成设施,用于根据结构化数据模型构建工具和其他应用程序。”)在下载文件之后,进入包含 Eclipse 文件夹的目录并运行 unzip emf-sdo-SDK-2.1.0.zip。例如:

清单 3. 运行 unzip emf-sdo-SDK-2.1.0.zip


% cd $JAVA_DIR
% ls
eclipse j2sdk1.4.2_08
% mv ~/emf-sdo-SDK-2.1.0.zip .
% unzip emf-sdo-SDK-2.1.0.zip
creating: eclipse/features/
creating: eclipse/features/org.eclipse.emf.ecore.sdo_2.1.0/
creating: eclipse/features/org.eclipse.emf_2.1.0/
inflating: ...

安装 XSD SDK V2.1
下载 XSD SDK V2.1。(根据项目 Web 站点所说,“XSD 是一个库,它提供了一个应用编程接口(API),用于按照 World Wide Web Consortium(W3C)XML Schema 规范的描述操作 XML 模式的组件。”)在下载文件之后,进入包含 Eclipse 目录的目录并运行 unzip xsd-SDK-2.1.0.zip。下面是一个例子:

% cd $JAVA_DIR
% mv ~/xsd-SDK-2.1.0.zip .
% unzip xsd-SDK-2.1.0.zip

如果提示您确认覆盖任何文件,那么只需按 y(小写)对每个问题回答 Yes。

安装 UML V2.0 Metamodel Implementation
要使用 TPTP 的 Unified Modeling Language(UML)特性,就需要安装 UML V2.0 Metamodel Implementation。如果正在使用 Eclipse V3.1.1,那么下载 V1.1.1 of UML2,然后在包含 Eclipse 的目录中释放它的存档文件:

% cd $JAVA_DIR
% mv ~/uml2-1.1.1.zip .
% unzip uml2-1.1.1.zip

安装 TPTP 运行时
对于下一步,下载 TPTP 运行时,这包含所有 TPTP 特性和集成两个系统所需的 Eclipse 插件。要安装 TPTP,进入包含 Eclipse 的目录并运行 unzip tptp.runtime-TPTP-4.1.0.zip。下面是一个例子:

% cd $JAVA_DIR
% mv ~/tptp.runtime-TPTP-4.1.0.zip .
% unzip tptp.runtime-TPTP-4.1.0.zip      

安装 Agent Controller
Agent Controller 是 TPTP 的一个重要组件,它使 Eclipse 能够启动应用程序并与这些应用程序进行交互,从而提取分析数据。下载适合您的操作系统的 Agent Controller 运行时。接下来,在包含 Eclipse 的目录中创建一个称为 tptpd 的目录,并将 Agent Controller 存档文件释放到这个目录中。要运行的命令是:

% mkdir $JAVA_DIR/tptpd
% cd $JAVA_DIR/tptpd
% mv ~/tptpdc.linux_ia32-TPTP-4.1.0.zip .
% unzip tptpdc.linux_ia32-TPTP-4.1.0.zip

如果看到两个下面这样的错误:

linking: lib/libxerces-c.so    
warning: symbolic link (lib/libxerces-c.so) failed

linking: lib/libxerces-c.so.24  
warning: symbolic link (lib/libxerces-c.so.24) failed

那么必须通过输入以下命令来手工重新创建这两个链接:

% cd $JAVA_DIR/tptpd/lib
% rm libxerces-c.so libxerces-c.so.24
% ln -s libxerces-c.so.24.0 libxerces-c.so
% ln -s libxerces-c.so.24.0 libxerces-c.so.24

添加 Agent Controller 目录
要使用 Agent Controller,必须将它的 lib 目录添加到 LD_LIBRARY_PATH 中。例如,如果正在运行 Linux 并采用以上步骤中给出的目录结构,那么用以下命令添加 $JAVA_DIR/tptpd/lib:

% export LD_LIBRARY_PATH=$JAVA_DIR/tptpd/lib:$LD_LIBRARY_PATH

还必须确保 Controller 的 lib 和 bin 目录的内容是可执行的。为此,运行:

% chmod +x $JAVA_DIR/tptpd/{bin,lib}/*

现在将配置和启动 Agent Controller 的脚本添加到 PATH:

% export PATH=$JAVA_DIR/tptpd/bin:$PATH

针对环境配置 Agent Controller
最后,要配置 Agent Controller 以便匹配环境。进入 Agent Controller 的 bin 目录,然后运行 SetConfig.sh。

% cd $JAVA_DIR/tptpd/bin
% ./SetConfig.sh

当配置脚本提示您进行选择时,接受默认设置。运行配置脚本会在 Agent Controller 的文件层次结构中创建文件 config/serviceconfig.xml。

测试 Agent Controller
为了测试 Agent Controller,运行 RAStart.sh。为了停止 Agent Controller,运行 RAStop.sh:

清单 4. 停止 Agent Controller
db% RAStart.sh
Starting Agent Controller
RAServer started successfully
% RAStop.sh
RAServer stopped, pid = 5891
RAServer stopped, pid = 5892
RAServer stopped, pid = 5893
RAServer stopped, pid = 5894
RAServer stopped, pid = 5895
RAServer stopped, pid = 5896
RAServer stopped, pid = 5897
RAServer stopped, pid = 5898
RAServer stopped, pid = 5899
RAServer stopped, pid = 5900
RAServer stopped, pid = 5901
RAServer stopped, pid = 5902
RAServer stopped, pid = 5904
RAServer stopped, pid = 5905
RAServer stopped, pid = 5906

现在完成了!重新启动 Eclipse。在 Eclipse 工具栏上应该会看到一个新按钮,如图 1 所示。这是 TPTP Profile 按钮。TPTP 已经安装了,您可以继续学习本教程了。
图 1. TPTP Profile 按钮


对 Java 应用程序进行分析
既然已经安装了 TPTP 和底层软件,现在就运行 Eclipse。

示例应用程序

要分析的 Java 应用程序见清单 5。

清单 5. 由少量对象组成的简单 Java 应用程序


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class SpaceShipToy {
  /*
  * To build a spaceship, you need a capsule, a booster,
  * three stages, and two monkeys (borrowed
  * from a Barrel of Monkeys).
  */
  public Capsule capsule = new Capsule();
  public Booster booster = new Booster();
  public Stage[] stage = new Stage[3];
 
  public SpaceShipToy()
  {
    for (int i = 0; i < 3; i++)
    stage = new Stage();
  }

  private void _killTime(int seconds)
  {
    if (seconds <= 0)
      return;
     
    for (int i = 0; i < seconds; i++);
  }
 
static final int MINUTE = 60;
  static final int CAPSULE = 2 * MINUTE;
  static final int BOOSTER = 5 * MINUTE;
  static final int STAGE = 3 * MINUTE;
  static final int MONKEY = 10 * MINUTE;
 
  class Capsule {
    public Monkey chimp1 = new Monkey(), chimp2 = new Monkey();

    public Capsule() {
      System.out.println("Start building the capsule...");
      _killTime(CAPSULE);
      chimp1.build();
      chimp2.build();
      System.out.println("Capsule complete.");
    }
  }
 
  class Booster   {
    public Booster() {
    System.out.println("Start booster...");
    _killTime(BOOSTER);
    System.out.println("Blast off.");
    }  
  }
 
  class Stage {
    public Stage() {
    System.out.println("start stage...");
    _killTime(STAGE);
    System.out.println("Stage complete.");
    }  
  }
 
  class Monkey {
    public void start() {
    System.out.println("Start the monkey business...");
    }
   
    public void build() {
    start();
    _killTime(MONKEY);
    finish();
    }
   
    public void finish() {
    System.out.println("Monkey business complete.");
    }
  }


  public static void main(String[] args) throws java.io.IOException
  {
    final int NUMBERTOYS = 9;
   
    BufferedReader in = new
      BufferedReader(new InputStreamReader(System.in));
    SpaceShipToy[] toys = new SpaceShipToy[NUMBERTOYS];
    String input = in.readLine().trim();
   
    System.out.println("Toy factory is up and running...");
    System.out.flush();

    for (int i = 0; i < NUMBERTOYS; i++)
      toys = null;
     
    while (!input.equalsIgnoreCase("q")) {
    if (input == null || input.length() != 1
      || !Character.isDigit(input.charAt(0))) {
      System.err.println ("Unknown option. Try 0-9, q");
      input = in.readLine().trim();
      continue;
    }
   
    int number = Integer.valueOf(input).intValue();
    if (number == 9) {
      new SpaceShipToy();
      System.out.println("Whoops... Lost one...");
    }
    else {
      if (toys[number] != null) {
        System.out.println("Shipping toy # " + number);
        toys[number] = null;
      }
      else {
        System.out.println("Building toy # " + number);
        toys[number] = new SpaceShipToy();
      }
    }
   
    input = in.readLine().trim();
  }
}
}

这个 Java 应用程序很简单:它 “构建” 玩具飞船并将它们 “发射” 到商店。每个玩具由一个 Java 对象代表,这个对象包含几个其他对象,这些对象各自代表玩具的一个部件。每个玩具部件都要花一定的时间来构建。
为了使用这个应用程序,按 0 到 8 数字键来构建玩具。如果再次按同一个键,构建的玩具就被 “发射”,相关联的对象被取消引用,从而可以被垃圾收集。因此,在任何时候在内存中最多可以有 9 个玩具(如果构建了所有 9 个玩具,而且都没有发射)。
按 9 键会创建一个未被引用的对象,这模拟了内存泄漏。按 q(小写)可以退出应用程序。

运行分析会话
使用 Eclipse 和 TPTP 来运行并分析 “玩具工厂”。TPTP 可以显示活动对象的数量、执行时间等等。要使用 Eclipse 和 TPTP:
1.    启动 Agent Controller。
2.    进入 Agent Controller bin 目录,然后运行 RAStart.sh:
% cd $JAVA_DIR/tptpd/bin
% ./RAStart.sh
3.    在 Eclipse 中,进入工作台并通过点击 File > New > Project 创建一个新的 Java 项目。从选项列表中选择 Java Project,然后点击 Next。
4.    在下一个窗口中,输入 Toy Maker 作为 Project Name,然后点击 Finish。标题为 “Toy Maker” 的新项目应该会出现在 Package Explorer 面板中。
5.    在这个项目中,在 example 包中创建一个称为 SpaceShipToy 的 Java 类。点击 File > New > Class。
6.    在弹出的窗口中,在 Package 域中输入 example 并在 Name 域中输入 SpaceShipToy。窗口中的其他设置保持不变。
7.    点击 Finish。现在应该会看到新类的骨架。
8.    将清单 1 中的代码复制到 Eclipse 类编辑器中,一定要留下 package example 声明,但是要替换空的类定义。保存代码以使修改持久化,这还会使 Eclipse 自动地重新编译类的新版本。
9.    如果要运行这个应用程序,点击 Run > Run...,双击 Java Application,选择 SpaceShipToy,然后点击 Run。要与这个应用程序进行交互,点击 Windows > Show View...,然后选择 Console。
10.    输入 1(数字一)并按 Return。屏幕应该与图 2 相似。

图 2. 在 Eclipse 下运行的玩具工厂


对同一个应用程序进行分析
要对同一个应用程序进行分析:
1.    点击 TPTP Profile,然后选择 Profile...。
2.    展开 Java Application 以显示 SpaceShipToy。注意,Profile 窗口与点击 Run 时出现的 Run 窗口相似,但是多了一个称为 Profile 的选项卡。
3.    点击 Profile 在分析器下启动这个应用程序。如果透视图没有自动切换,那么点击 Window > Open Perspective > Other...,然后选择 Profiling and Logging。
4.    当 Profiling and Logging 透视图出现时,展开 Profiling Monitor 视图的内容,然后选择以 <monitoring> 开头的行。在选择这一行时,出现一个控制台视图。
5.    输入 0、1、2 和 9。屏幕应该与图 3 相似。

图 3. Profiling and Logging 透视图与正在运行的应用程序

6.    点击 Memory Statistics 视图,然后展开与 example 包相关联的行。这个视图应该与图 4 相似。这里有 4 个对象实例:三个代表 “构建的” 玩具,一个代表未被引用的玩具。

图 4. 在构建三个玩具对象和一个未被引用的玩具之后的内存消耗

Memory Statistics 视图中的列记录了实例和内存使用统计数据:
•    Total Instances 反映一个类的实例总数。
•    Live Instances 显示有多少个实例仍然被引用,还没有被垃圾收集器收集。
•    Collected 统计垃圾收集器已经收集了多少个类实例。
•    Total Size (bytes) 和 Active Size (bytes) 分别显示所有实例使用的累积内存总量(一种高水位标志)和活动实例当前使用的内存量。
结束试运行
要结束这一次试运行,切换回控制台视图,然后再次按 0、1 和 2 数字键。点击 Monitoring 视图中的 trash can 图标强迫实施垃圾收集。好的垃圾收集器会收集所有未被引用的对象。在任何时候,都可以通过点击 Refresh 刷新当前透视图中的所有视图,见图 5。
图 5. Refresh 按钮

寻找需要的数据
Profiling and Logging 透视图提供了许多视图,其中提供关于应用程序状态的大量数据。要查看视图列表,点击 Window > Show View > Other...,然后展开 Profiling and Logging 下面的列表。这个列表应该与图 6 相似。

图 6. Profiling and Logging 视图的列表


收集数据来填充视图
根据您的目标和面对的问题,可以收集数据来填充所有这些视图或者其中一个视图。在前一节中,收集的惟一数据是内存统计数据,这些数据填充在 Memory Statistics 视图中。Monitoring 视图与图 7 相似。

图 7. Monitoring 视图中的基本统计数据

最下面的展开的列表表明,当前的分析配置只包含内存使用情况的统计数据。我们来创建一个收集尽可能多信息的新的分析配置,这样您就能够看到分析和性能工具提供的所有度量:
1.    点击 TPTP Profile 按钮中的小箭头,然后选择 Profile...。
2.    在 Profile 窗口中,选择 SpaceShipToy,然后点击窗口底部左边的 New。
3.    在最右边面板的顶部,在 Name 域中输入 Lots of Data ,然后点击 Apply。
4.    点击 Profiling 选项卡,然后点击 Add...。
5.    在下一个窗口中,输入 All 作为 Profile set name 并在 Description 域中输入 All of the data that's available。点击 Next。
6.    下一个面板让您选择要收集的数据。展开所有选择,然后选中所有复选框,如图 8 所示。

图 8. 要选择的度量

7.    点击 Execution Time Analysis。
8.    选择 Collect method CPU time information 复选框,然后选择 Show execution flow graphical details 选项。再次点击 Next。下一个窗口(见图 9)允许过滤掉您不感兴趣的类。

图 9. 从分析中排除无关的类

9.    出于这个例子的目的,点击面板顶部的 Add... 来添加一个新的过滤器集。将这个过滤器集命名为 No Monkey Business 并点击 OK。
10.    点击规则列表右边的 Add... 在过滤器集中添加一个新规则。在 Class name 域中输入 example.SpaceShipToy 并在 Method name 域中输入 main(星号),选择 EXCLUDE 作为 Rule(见图 10),然后点击 OK。

图 10. 编辑过滤器规则

11.    在更大的窗口中,点击 Apply。
12.    现在已经定义了要分析的应用程序和要收集的度量。点击 Profile。
13.    在 Profiling and Logging 透视图中,点击 Memory Statistics 视图。应该会看到,根据刚才创建的规则,没有对方法 example.SpaceShipToy.main() 执行度量。
提示和技巧
TPTP 工具提供了丰富的特性,可以帮助您深入地了解应用程序。另外,因为 TPTP 与 Eclipse 的其余部分很好地集成在一起,您会发现许多方便之处。
为了帮助您,下面提供一些提示和技巧。

快速建立数据过滤器
启动一个分析会话并打开 Execution Statistics 视图。这个视图显示一个应用程序中的所有类和方法(至少是还没有在过滤器集中过滤掉的那些)。在这个视图中右击,打开图 11 所示的快捷菜单。

图 11. 快捷菜单

点击 Filter out...,选择 Profiling,然后点击 OK。在下一个窗口(见图 12)中,输入 Monkey Business 作为过滤器名并输入 build 作为过滤器字符串,然后选择 Filter by 下面的 Method name 选项。点击 OK 并再次点击 OK。
图 12. Edit Filter 窗口

视图应该会改为只显示 example.SpaceShipToy$Monkey.build() 方法的统计数据。
要想恢复视图,再次看到所有方法,可以点击 Filter(见图 13)并选择 No filter。要想编辑任何过滤器,可以点击同一个按钮并选择 Manage filters...。
图 13. Filter 按钮



跳到源代码
仍然留在 Execution Statistics 视图中。双击 SpaceShipToy$Booster 类。这时就会切换到 Java 透视图并直接跳到内部类 Booster 的定义。内存分析视图和 Eclipse 代码编辑器之间的这种连接是非常有价值的特性。

高级的复杂过滤器
可以使用 Edit Filter 窗口的 Advanced 选项卡来构建任意复杂的过滤器。高级过滤器 是一系列规则,其中每个规则列出一个属性、一个条件(比如 “equal”、“not equal” 和 “like”)和一个值。您想知道一个实例消耗了多少内存吗?这可以用高级过滤器来表达。

组织和排序
大多数数据视图可以按照包、类和方法对数据进行组织。通过点击大多数数据视图顶部的三个按钮之一(见图 14),可以快速地改变数据的组织方式。
图 14. 用于组织数据的三个按钮

从左到右,分别是按照包、类和方法进行组织的按钮。
还可以通过点击任何列标题,对所有数据进行排序。点击列标题一次,就对这个列按照升序进行排序;再次点击同一个列标题,就按照降序显示数据。

使用 UML2 序列图深入了解代码
TPTP 提供了另一个对了解正在运行的应用程序有帮助的特性:UML2 序列图。这个图不但显示类和方法之间的调用序列,还可以突出显示热点,也就是消耗了大部分应用程序执行时间的代码部分。

在序列图中查看代码
要使用 UML2 序列图查看代码:
1.    退出正在分析的所有玩具工厂应用程序实例。
2.    点击 TPTP Profiling 按钮中的小箭头。选择 Profile...,选择 SpaceShipToy,点击 Profiling 选项,然后选择 All。
3.    点击 Apply(如果需要的话),然后点击 Profile。
4.    当应用程序在 Profiling Monitor 视图中启动时,右击刚启动的进程并选择 Open With... > UML2 Thread Interactions 来打开 UML2 class Interactions 视图。因为这个应用程序刚刚启动,所以这个图只显示了对 main() 的调用,如图 15 所示。

图 15. 只显示 main() 调用的简单 UML 图

5.    切换到控制台视图并与应用程序进行交互,从而产生更多的方法调用。然后切换回 UML2 Trace Interactions 视图。UML 图应该已经增大了,可能与图 16 相似。

图 16. 示例应用程序的 UML2 视图

6.    将鼠标指针放在左边空白处中的红色条上,就会显示一个表示 CPU 时间消耗的刻度条(见图 17)。

图 17. CPU 消耗刻度条

7.    深红色表示最大。在这个应用程序中,SpaceShipToy 类的构造过程显然是瓶颈。
对对象引用进行编目
另一个对正在运行的应用程序进行分析的有用特性是 Object References 视图,这个视图显示应用程序中每种对象的引用数量。如果您的 Java 代码看起来消耗了过多的内存,那么收集并查看对象引用可以帮助您找到出问题的代码。

使用 Object References 视图
使用 Object References 视图与使用其他 TPTP 视图一样容易:
1.    终止正在分析的所有进程。
2.    在 Profiling Monitor 中右击并选择 Unload Profiling Data。按照提示删除到目前为止收集的所有数据。
3.    选择以前监视的所有进程并按 Delete。出现提示窗口时,选择 Do not delete contents,然后点击 Yes。
4.    对玩具工厂应用程序启动一个新的分析会话。切换到控制台视图,然后按 1 2 9 来创建两个玩具和未被引用的第三个 “玩具”。
5.    通过在 Profiling Monitor 视图中点击 Collect object references,收集正在使用的对象(见图 18)。

图 18. Collect Object References 按钮

6.    在 Eclipse 工具栏上,点击 Open Object References(见图 19)来打开 Object References 视图。Object References 视图列出应用程序中使用的每个对象和对应的引用数量。

图 19. Object References 按钮

7.    展开 SpaceShipToy。引用表应该与图 20 相似。已经创建了三个玩具,所以这个表是准确的,因为每个玩具包含一个推进器、一个太空仓(其中有两只猴子)和三级火箭。

图 20. 示例应用程序在某一时刻的 Object References 视图


对本地 Java 应用程序使用 TPTP
除了对通过 Eclipse 工作台构建和启动的 Java 应用程序进行分析之外,还可以分析本地计算机上已经在运行的 Java 应用程序(应用程序也可以在远程计算机上,但是这里不讨论分析远程应用程序的过程)。可以通过 TPTP 附着 到进程上。附着之后,就可以使用前面学习过的所有工具来探索和观察内存分配。

附着到本地 Java 应用程序
要附着到本地 Java 应用程序:
1.    退出和删除 Profiling Monitor 视图中所有正在运行的进程。
2.    打开一个命令窗口并确认 PATH 和 JAVA_HOME 环境变量指向 JRE。
3.    确保 LD_LIBRARY_PATH 包含 TPTP 库。在测试系统上,这些变量如下所示(根据您的系统配置,路径名和目录名可能不一样):

% printenv
.
PATH=/bin:/usr/bin:/usr/X11R6/bin:/home/mstreicher/java/jdk/bin
JAVA_HOME=/home/mstreicher/java/jdk
JAVA_DIR=/home/mstreicher/java
LD_LIBRARY_PATH=/home/mstreicher/java/tptpd/lib:

4.    确保 TPTP Agent Controller 正在运行。进入包含 Agent Controller 的目录,然后停止并重新启动这个守护进程:

% cd $JAVA_DIR/tptpd/bin
% ./RAStop.sh
RAServer stopped, pid = 3163
RAServer stopped, pid = 3164
.
RAServer stopped, pid = 18108
% ./RAStart.sh
Starting Agent Controller
RAServer started successfully

5.    将玩具工厂应用程序作为单独的独立 Java 应用程序运行:
o    进入包含示例应用程序的工作空间目录,可能是 $HOME/workspace/Toy Maker。在这个目录中,应该会看到一个称为 example 的目录,其中包含 SpaceShipToy.java 的代码和相关联的 .class 文件。
o    将当前工作目录(.(点号))添加到 CLASSPATH:

% cd $HOME/workspace/Toy Maker
% ls -F
example
% export CLASSPATH=.:$CLASSPATH

6.    用 -XrunpiAgent:server=enabled 选项通过 TPTP Agent Controller 启动应用程序。enabled 模式以普通方式启动 Java 应用程序并在后台运行控制器。(如果在附着到应用程序之前不想执行它,那么使用 controlled 模式。)

% java -XrunpiAgent:server=enabled example/SpaceShipToy

7.    返回到 Eclipse,然后点击 TPTP Profile 按钮中的小箭头。选择 Profile...。在左边的列表中,双击 Attach - Java Process。
8.    在下一个窗口中,在 Name 域中输入 Toys,然后选择 localhost 作为主机。点击 Apply。
9.    通过点击 Agents 选项卡选择一个代理,如图 21 所示。

图 21. 选择要附着的代理

点击显示的代理(如果当前没有在分析其他应用程序或进程,那么应该有一个代理),然后点击 >。为了保存这一修改,再次点击 Apply。
10.    通过点击 Profiling 选项卡并选择一个分析集,从而选择要收集什么数据。可以选择 All,就会采用前面创建的分析集。
11.    点击 Apply,然后点击 Profile。Eclipse 应该会切换到 Profiling and Logging 透视图。
12.    在大多数系统上,这时会出现与图 22 相似的窗口。

图 22. Profiling 提示

这个警告是正常的,它提醒您尽管已经附着到了这个进程,但是必须手工启动监视。为了启动监视,右击刚启动的分析进程,然后选择 Start monitoring。
13.    切换回命令窗口,与应用程序进行交互。再返回 Eclipse 查看正在运行的应用程序的分析数据。完成之后,点击 Terminate Process 按钮(见图 23)。

图 23. Terminate Process 按钮

将在命令窗口中杀死进程:

% java -XrunpiAgent:server=enabled example/SpaceShipToy
.
Stage complete.
Start stage...
Stage complete.
Start stage...
Stage complete.
zsh: killed   java -XrunpiAgent:server=enabled example/SpaceShipToy
%

结束语
本教程演示了如何通过分析代码来调整和改进 Java 应用程序。通过使用 Eclipse TPTP,可以运行代码并探测哪些代码段浪费了内存并导致性能降低。TPTP 还提供了其他工具,可以从大型日志文件中提取信息,以及自动地获取和分析测试结果。
TPTP 中的其他工具包括一个记录-回放设施(可以测试在 Eclipse 下运行的应用程序的 GUI)和一个称为 XRay 的特殊分析器(专门用于分析源自 Eclipse 平台的应用程序)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值