FeaturesPluginsDocs & SupportCommunityPartners

NetBeans Profiler 5.5 教程

此文章适用于 NetBeans Profiler 5.5、5.5.1 或 NetBeans 6.0 Milestone 7 及更高版本。

预计持续时间:70 分钟

NetBeans Profiler 是一个功能强大的工具,它提供了有关应用程序运行时行为的重要信息。NetBeans Profiler 可以监视线程状态、CPU 性能以及内存使用情况,而且其运行开销相对来说较少。本教程将向您介绍如何使用 NetBeans Profiler 来执行以下任务:

  • 监视应用程序的运行时行为,其中包括:

    • 堆内存大小
    • 垃圾回收统计信息
    • 线程计数
    • 线程状态:运行、休眠、等待、受阻
  • 确定应用程序方法使用的 CPU 时间
  • 监视应用程序创建对象的过程
  • 分析 Java SE 和 Java EE 应用程序

先决条件

本教程假定您已具备了一些基本的 Java 编程经验。

教程所需的软件:

  • 下载并安装 Java 2 Platform Standard Edition 5.0 Update 4(或更高版本)。请注意,NetBeans IDE 需要完整的 JDK,而不仅仅是 JRE。请记住此安装目录。
  • 下载并安装 NetBeans IDE 5.5(或更高版本)。请记住此安装目录。当系统提示您选择 JDK 时,请指定 5.0 Update 4(或更高版本的)JDK。
  • 下载并安装 NetBeans Profiler 5.5(或更高版本)

    Profiler 安装程序会要求修改 NetBeans IDE 安装;请指定 NetBeans IDE 的安装目录。

  • 要完成最后的练习(分析 Enterprise Java Beans 模块),请下载并安装 Java EE 5 SDK。Java EE 5 SDK 包含 Sun Java System Application Server Platform Edition 9(Sun Java System Application Server 同时以其开放源代码项目名称 GlassFish 命名)。请使用 NetBeans IDE 的服务器管理器(“工具”>“服务器管理器”)在 IDE 中注册 Sun Java System Application Server。
  • 下载教程 zip 文件,其中包含了练习中使用的项目。

本文使用的表示法

  • <NETBEANS_HOME> - NetBeans IDE 安装目录
  • <USER_HOME> - 用户的 home 目录
  • <tutorial_root> - 教程 zip 文件的解压缩目录
    • 本文档将使用 <tutorial_root> 来表示本教程中使用的解压缩教程 zip 文件所在的目录。教程 zip 文件的名称为 profilertutorial.zip。
    • 将教程 zip 文件解压缩到 <tutorial_root> 目录后,系统会创建一个名为 netbeansprofiler 的子目录。例如,在 Windows 中,如果已将教程 zip 文件解压缩到驱动器 E:\ 根目录下,则系统会创建 E:\netbeansprofiler 子目录。在 Solaris/Linux 中,如果已将教程 zip 文件解压缩到 /home/username 目录中,则系统会创建 /home/username/netbeansprofiler 子目录。

教程练习

参考资源:

安装并配置教程环境

在继续阅读本教程之前,请执行以下操作:

  • 启动 NetBeans IDE,并确认 IDE 正在运行:

    • 在 Windows 中,双击 NetBeans IDE 图标。
    • 在 Solaris/Linux 中,打开终端窗口,然后键入 <NETBEANS_HOME>/bin/netbeans。
  • 通过选择“性能分析”>“帮助”>“关于 Profiler...”,验证是否安装了 NetBeans Profiler。


监视 Swing 应用程序中的线程状态(15 分钟)

在本练习中,您将学习如何使用 NetBeans Profiler 监视 Java SE 应用程序中的线程状态。这样,您就可以诊断样例 Swing 应用程序中的性能问题。

背景信息:

Swing 库为 Java SE 应用程序提供了图形用户界面组件。Swing 库使用多个线程,利用 NetBeans Profiler 这一功能强大的工具,您可以分析每个线程中执行的所有处理活动,这种分析信息可用来解决性能问题。

执行步骤:

  1. 选择“文件”>“打开项目”。找到 <tutorial_root>/netbeansprofiler/exercises 文件夹。选择 "exercise1" 文件夹,然后单击“打开项目文件夹”按钮。
  2. 在“项目”窗口中,右键单击 "exercise1" 条目,然后选择“清理并生成项目”。然后,再次右键单击 "exercise1" 条目并选择“运行项目”。此时,将显示该程序的窗口,如下所示。

    查看应用程序的窗口

  3. 将 "Seconds Before Notification" 设置为 30。
  4. 单击 "Start!" 按钮。请注意,该程序并没有相应地刷新窗口。
  5. 单击 "Exit" 按钮。请注意,该程序根本并未作出任何响应。
  6. 要了解其他问题,请将另一个窗口放在该窗口的某一部分上,以遮挡该窗口视图。当移开另一个窗口时,您会注意到样例应用程序没有相应地刷新其窗口。如下面的示例所示。

  7. 30 秒后,最终将显示一个消息框,如下所示。单击消息框上的 "OK" 按钮。

  8. 应用程序窗口将再次开始响应。单击 "Exit" 按钮将其关闭。
  9. 选择“性能分析”>“分析主项目”。
  10. 如果出现一个对话框,询问您是否允许修改项目生成脚本,请单击“确定”。如下面的示例所示。

  11. 将显示“选择性能分析任务”对话框。单击较大的“监视应用程序”按钮。
  12. 请选中“启用线程监视”复选框。
  13. 单击“运行”按钮。
  14. 如果显示一个对话框,指示您必须先收集 Profiler 校准信息,请单击“确定”按钮。如下面的示例所示。

    完成校准后,Profiler 会显示一个对话框,请单击“确定”按钮。如下面的示例所示。

    要进行性能分析,请返回至上面的第 9 步。

  15. 完成上述步骤后,将启动该应用程序,并且 IDE 会显示 "Profiler" 控制面板,如下所示。

  16. Profiler 将在其主窗口中显示线程状态,如下面的示例所示。

  17. 它使用颜色编码来显示线程状态。

    • 绿色:线程正在运行或准备运行。
    • 紫色:线程正在调用 Thread.sleep(),处于休眠状态。
    • 黄色:线程正在调用 Object.wait(),处于等待状态。
    • 红色:线程在尝试访问同步的程序块或方法时受阻。

  18. 找到样例 Swing 应用程序的窗口(NetBeans IDE 窗口可能在其上面)。单击样例应用程序中的 "Start!" 按钮,同时监视标记为 AWT-EventQueue-0 的线程所发生的变化。它将变为绿色并持续这种状态整整 30 秒钟,如以下样例所示。

    此图形显示了应用程序没有响应的原因。标记为 AWT-EventQueue-0 的线程是 Swing 用来处理窗口事件的事件分发线程 (Event Dispatch Thread, EDT)。在正常运行的 Swing 应用程序中,EDT 的大部分时间应该处于等待状态而运行时间很少,因为它只有在分发事件时才会运行很短的一段时间。但是,如果应用程序中的事件处理程序未立即返回,则程序将停止响应,就像在此示例中一样。

  19. 30 秒后,将显示应用程序的消息框。找到该消息框(NetBeans IDE 窗口可能在其上面)并单击 "OK" 按钮。然后,单击样例应用程序的 "Exit" 按钮,将其关闭。
  20. “项目”窗口与 "Profiler" 控制面板共用同一个空间区域;单击“项目”标签将会显示“项目”窗口。
  21. 在“项目”窗口中,双击 "exercise1" 条目将其展开,然后展开“源包”和 "profilingthreads" 条目。右键单击 "DisplayForm.java" 条目,然后选择“打开”。
  22. 在包含 DisplayForm.java 的编辑器窗口中,取消第 132 行至第 157 行的代码块注释。提示:如果编辑器没有显示行号配置,请选择“视图”>“显示行号”。
  23. 在包含 DisplayForm.java 的编辑器窗口中,删除(或注释掉)第 122 行到第 128 行的代码块。下图突出显示了此代码块。

  24. 选择“文件”>“保存”。您刚才删除了未正确使用 EDT 的代码,并利用了更稳定、可靠的解决方案来替代它。现在,应用程序可以及时地作出响应了。
  25. 选择“生成”>“生成主项目”(或按 F11 键)。
  26. 选择“性能分析”>“分析主项目”。
  27. 将显示“选择性能分析任务”对话框。单击较大的“监视应用程序”按钮。
  28. 确保选中了“启用线程监视”。
  29. 单击“运行”按钮。
  30. 在显示样例程序时,单击 "Start!" 按钮。请注意,此时的 Profiler 线程图已经发生了变化,如以下示例所示。

    EDT 为黄色,应用程序创建的名为 "Our SwingWorker #1" 的线程为绿色。由于 EDT 不是用来执行耗时任务的,因此,按钮和其他程序控件仍保持响应的状态。

  31. 在样例程序中单击 "Exit" 按钮。
  32. 右键单击 Profiler 图形中的 AWT-EventQueue-0 线程,然后选择“线程详细信息”。Profiler 会显示一个饼图,表明了每种状态所花的时间;如以下示例所示。

    该图形可以帮助您判断程序在每个线程中所花费的时间是否恰当。上述示例是代码修复后的示例,因此,它显示了 EDT 在大部分时间都处于等待状态的情形,这也正是该线程应具有的行为。

  33. 在“项目”窗口中,右键单击 "exercise1" 条目,然后选择“关闭项目”。

小结:

在本练习中,您学习了如何使用 Profiler 来启动应用程序,以及如何解释 Profiler 的线程信息图形,以此来跟踪 Swing 应用程序中的性能问题。

返回页首

确定方法使用的 CPU 时间(15 分钟)

在本练习中,您将学习如何使用 Profiler 来确定某个应用程序的方法所花费的时间。

背景信息:

CPU 的性能问题通常与应用程序的特定功能有关。例如,在报告系统中,某个报告的运行速度可能比其他报告慢。只分析应用程序中出现性能问题的部分,可以大大减少 Profiler 产生的开销。在本练习中,您将使用 NetBeans Profiler 来检查 Web 应用程序中 CPU 的使用情况。在练习 3 中,我们仍然使用该样例 Web 应用程序来说明如何通过 Profiler 查找内存泄漏。

执行步骤:

  1. 选择“文件”>“打开项目”。找到 <tutorial_root>/netbeansprofiler/exercises 文件夹。选择 exercise2 文件夹,并确保选中“作为主项目打开”。单击“打开项目文件夹”按钮。
  2. 从菜单中选择“生成”>“清理并生成主项目”。
  3. 从菜单中选择“性能分析”>“分析主项目”。如果出现一个对话框,询问您是否允许修改项目生成脚本,请单击“确定”。
  4. 单击“选择性能分析任务”对话框中的“分析性能”按钮。
  5. 选择“部分应用程序”单选按钮。然后,单击“部分应用程序”单选按钮旁边的“选择”按钮。将显示“指定根方法”窗口。
  6. 在“指定根方法”窗口中,单击“从项目添加...”按钮以添加要分析的根方法。将显示“选择方法”窗口。
  7. 在“类名”文本字段中,键入 demo.Performance,然后按 Enter 键。

    查看“选择方法”对话框

  8. 在根方法列表中单击 processRequest 方法以将其选中,然后单击“确定”按钮。您刚才已将 demo.Performance.processRequest 选中为性能分析的根方法。这意味着,Profiler 将分析 demo.Performance.processRequest 方法以及它调用的所有方法,以及这些方法又调用的所有方法,依此类推。Profiler 将从 demo.Performance.processRequest 开始,通过分析方法调用图形来确定哪些方法需要分析。它只分析那些需要分析的方法,应用程序的其余部分将在没有任何性能分析开销的情况下继续以最快的速度运行。
  9. 在“指定根方法”窗口中单击“确定”按钮。
  10. 在“分析性能”窗口中,从“过滤器”列表中选择“快速过滤器”,然后单击“快速过滤器”条目旁边的 "..." 按钮以指定进行分析的方法。将显示“设置快速过滤器”窗口。确认已选中了“排除”单选按钮。然后,在“过滤器值”文本字段中输入 org.apache 并单击“确定”按钮。这样,Profiler 将不分析 org.apache 包(及其子包)中的所有方法,即使这些方法被选定的根方法调用也是如此。这会减少性能分析的开销,并过滤掉无关的信息。

    “设置快速过滤器”对话框

  11. 在“选择性能分析任务”窗口中,单击“运行”按钮。如果出现一个对话框,要求您提供校准信息,请单击“确定”按钮;在 Profiler 显示的对话框说明校准已完成后,请单击该对话框的“确定”按钮。
  12. IDE 将启动捆绑的 Tomcat 服务器,并在 Web 浏览器窗口中显示 Web 应用程序的 index.jsp 页。同时,将在后台运行 Profiler。注意:缺省情况下,将在成为焦点的浏览器窗口中显示 index.jsp 页;您还需要打开另一个浏览器窗口,以便在运行 Web 应用程序时可以阅读这些说明。
  13. 因为您已选择了 demo.Performance.processRequest 作为根方法,所以,您需要使用让根方法运行的 Web 应用程序部分:在 Web 浏览器中,单击 "Performance Problems" 以转至 Performance 演示页。在 Performance 演示页上的输入文本字段中输入 123456。请不要选中 "optimized" 选项。单击“提交查询内容”按钮,计算小于或等于 123456 的最大素数。
  14. 需要几秒钟的时间才能出现响应,这是因为计算最大素数的算法存在一些性能问题,同时,在监视 processRequest 方法的性能时,Profiler 也会产生一些开销。当浏览器中显示 "123449" 结果后,请单击 “获取结果”按钮 按钮,或者选择“性能分析”>“生成收集结果的快照”。单击位于 CPU 使用情况快照底部的“组合”标签。Profiler 将显示最新的性能结果,如下所示。

    查看性能结果。

    顶部窗口显示了从根方法开始的完整方法调用图形。底部窗口是重点描述部分;它显示了应用程序中的热点,即执行时间最长的那些方法。

  15. 要查看并解释这些结果,请注意 processRequest 方法总共运行的时间为 3745 毫秒 (ms)。然而您会发现,运行 processRequest 方法本身的指令只花费了很少的时间,processRequest 的“自用时间”仅为 4.5 毫秒。绝大部分时间花在了 processRequest 调用的其他方法上。底部窗口中显示的热点是按“自用时间”进行排序的。通过查看该列表,您可以看到 calculate 方法占用了 97.8% 的执行时间。考虑到为 calculate 方法分配的工作量,这就不足为奇了。
  16. 为了帮助您确定如何优化应用程序,NetBeans Profiler 可以识别出代码中无法预料的瓶颈,或者妨碍应用程序随意缩放的瓶颈。单击热点列表中的 calculate 条目以了解时间究竟花在什么地方,这会更新调用图形窗口以显示 calculate。因为 calculate 方法不调用任何其他方法,所以请右键单击 calculate 条目,然后选择“转至源代码”以便检查源代码。您会发现它使用了效率很低的算法,所以应该重新设计这种算法。
  17. 选择“性能分析”>“重置收集的结果”以清除 Profiler 的缓冲区。要将 calculate 的运行时与优化的算法 calculate2 作比较,请在 Web 浏览器中选中 "optimized" 选项,然后单击“提交查询内容”。等待显示结果,然后重新选择“性能分析”>“生成收集结果的快照”。请注意,processRequest 方法只运行了 8.6 毫秒,而 calculate2 方法只需要 6.49 毫秒!

    查看性能结果。

  18. 注意:我们将继续在本练习的基础上进行下面的练习,因此,请不要关闭任何窗口。

小结:

在本练习中,您学习了如何使用 Profiler 对单个方法及其调用的所有方法执行性能分析。

返回页首

分析对象创建过程以查找内存泄漏(20 分钟)

作为练习 2 的后续练习,我们将通过本练习学习如何从一种类型的性能分析切换到另一种更重要的性能分析,以及了解如何分析某些 Profiler 图形以监视应用程序创建对象的过程。下面将显示一个内存泄漏示例。

执行步骤:

  1. 本练习是在练习 2 的基础上进行的,因此,请务必遵循练习 2 中的步骤。
  2. 从菜单中选择“性能分析”>“修改性能分析”。
  3. 在“选择性能分析任务”对话框中,单击较大的“监视应用程序”按钮。
  4. 单击“运行”按钮。IDE 将会在左侧显示 "Profiler" 控制面板。单击 查看“遥测概览”按钮 按钮,或者选择“性能分析”>“视图”>“遥测概览”。NetBeans Profiler 将在底部的输出窗口中显示三个图形,如下所示(单击可查看完整图形)。

    查看监视器图形

    在左侧的图形中,红色的阴影部分表示分配的 JVM 堆大小。紫色的覆盖部分表示实际使用的堆空间大小。在上面的示例中,上次更新所分配的堆大小已超过了 10 MB。其中,实际用来保存 Java 对象的堆大小略大于 5 MB。

    右侧图形显示了 JVM 中的活动线程数。

    中间的图形显示了两种重要的堆统计信息。

    • 蓝线(在本示例中,它位于图形底部)是 JVM 执行垃圾回收的时间占执行时间的百分比,它是以图形右侧上的 Y 轴为参照绘制的。JVM 执行垃圾回收所花的时间不能用来运行应用程序。因此,如果蓝线占据较大的百分比,则需要考虑调整 JVM,方法是:配置更大的堆大小(请参阅 -Xmx 参数文档),或者转而使用不同的垃圾回收算法
    • 红线表示存活的年代数,它是以图形左侧的 Y 轴为参照进行绘制的。存活年代数是指 JVM 堆上所有 Java 对象不同生存期的数量,其中“生存期”被定义为对象存活时垃圾回收的次数。如果存活年代数的值较小,则表明堆上的大部分对象的存活时间基本相同。但是,如果存活年代数的值随着时间的变化而增长到一个很高的比率,则表明应用程序正在分配新的对象,同时保持对已分配的多个旧对象的引用。如果应用程序实际上不再使用这些旧对象,则应用程序就是在浪费(或“泄漏”)内存。
  5. Profiler 可以对 CPU 性能或内存使用情况进行详细的分析,但不能同时进行这两种分析。要了解有关在 JVM 堆上分配对象以及执行对象的垃圾回收的详细信息,请修改 Profiler 的设置。单击 查看“修改性能分析”按钮 按钮,或者选择“性能分析”>“修改性能分析”。
  6. 单击“分析内存使用情况”按钮。
  7. 选择“记录对象创建和垃圾回收”单选按钮。
  8. 选中“记录分配的栈跟踪”复选框。
  9. 单击“确定”按钮。
  10. 现在,您已经选择了分析内存使用情况,您需要运行应用程序以确定它是否有效地使用了内存。在浏览器中,单击“后退”按钮,直至重新显示应用程序的 index.jsp 页。然后,单击 "Memory Leak" 按钮以转至 MemoryLeak 演示页。
  11. 在 MemoryLeak 演示页上,单击 "Start Leaking"。
  12. 请注意存活年代数图形中的峰值,如以下示例所示。这表明可能出现了内存泄漏。

    存活年代数图形所示的峰值。

  13. 选择“性能分析”>“视图”>“实时结果”。Profiler 将显示 JVM 堆中分配的对象的动态视图。缺省情况下,它将按每个类的所有实例使用的字节数进行排序。由于怀疑可能出现了内存泄漏,因此,请单击“年代数”列,按每个类的不同对象生存期数量对显示结果进行排序。下面显示了得到的显示结果示例。

    前期的年代数图形。

    这些列提供了对象分配和内存使用情况信息。

    • “分配的对象”(右数第三列)是 Profiler 正在监视的对象数。在本示例中,共监视了 23 个 float[] 实例。缺省情况下,该数字约为应用程序实际分配的对象数的 10%。通过只监视已创建对象的某部分,Profiler 可以显著地减少它在 JVM 中的开销,这样,应用程序就几乎可以按最快的速度运行了。
    • “活动对象”是仍在 JVM 堆中并因此占用内存的已分配对象数。
    • 两个“活动字节”列显示了活动对象所占用的堆内存量。一个列显示图形,另一个列显示文本。
    • “平均生存期”值是使用活动对象计算的。每个对象的生存期是它存活时的垃圾回收次数。生存期总和除以活动对象数得到的结果就是平均生存期。
    • “年代数”值是使用活动对象计算的。与平均生存期相同,对象生存期是它存活时的垃圾回收次数。“年代数”值是活动对象的不同生存期数量。
  14. 随着程序继续运行,Profiler 将更新显示结果。请留意 float[]double[] 条目。请注意其年代数值是如何持续增加的。结果是,float[]double[] 在列表中持续上移。最终,它们会显示在列表的顶部,紧靠 java.util.HashMap$Entry(其年代数值也在不断增加)下面。随着应用程序继续运行,java.util.HashMap$Entryfloat[]double[] 年代数值持续增加,但任何其他类没有增加。如下面的示例所示(单击可查看完整图形)。

    后期的年代数图形。

  15. 要了解导致年代数值持续增加的原因,请选择“性能分析”>“生成收集结果的快照”。按年代数对显示结果进行排序。右键单击 double[] 条目,然后选择“显示分配栈跟踪”。Profiler 将显示所有分配了一个或多个 double[] 对象的方法。如下面的示例所示(单击可查看完整图形)。

    double[] 栈跟踪。

    请注意,在分配了 double[] 对象的方法中,只有一个方法创建了具有较大年代数值的 double[] 对象。该方法是 run(),它位于具有相应名称 demo.memoryleak.LeakThread 的类中。

  16. 右键单击 run() 方法条目,然后选择“转至源代码...”。Profiler 将显示源代码,如下所示。

    引起泄漏的代码

    请注意,正在分配 double[]float[] 对象,并随后将其放在了 HashMap 中。但一直未删除它们,这意味着,HashMap 保留的引用将会妨碍 JVM 对这些对象进行垃圾回收。这是非常典型的 Java 内存泄漏:将对象放在 Map 中,然后就忘记处理它们了。由于本示例中使用的 Map 就是 HashMap,因此,关联的 java.util.HashMap$Entry 对象也出现了泄漏。

  17. 其他佐证:如果返回到“内存结果”标签,右键单击 java.util.HashMap$Entry 条目,然后选择“显示分配栈跟踪”,则会看到更重要的栈跟踪列表。尝试展开栈跟踪中的节点,以了解能否方便地找到 demo.memoryleak.LeakThread 类中的 run() 方法所进行的调用。
  18. 选择“性能分析”>“停止”来结束性能分析会话,或者单击 “停止”按钮 按钮。
  19. 在“项目”窗口中,选择 "exercise2" 条目,然后从菜单中选择“文件”>“关闭 "exercise2"”。

小结:

在本练习中,您学习了如何使用 Profiler 来监视应用程序创建对象的过程。您还了解了 Profiler 在应用程序出现内存泄漏时所提供的信息类型。

返回页首

分析 Enterprise Java Beans 模块(20 分钟)

在本练习中,您将学习如何使用 NetBeans Profiler 中提供的特定支持来分析 Enterprise Java Beans (EJB)。您还将学习如何充分利用 Profiler 的过滤器来控制性能分析开销和报告的信息量。

背景信息:

NetBeans Profiler 可以为 EJB 性能分析提供特定的支持。例如,可以轻松地启动性能分析会话,然后运行一个要调用分析的 EJB 的独立应用程序。由于 EJB 在应用服务器中运行,因此需要使用特定的方法来最大限度地减少性能分析开销。Profiler 还提供了一些工具,可以帮助查找在独立线程中对 EJB 进行的调用。

执行步骤:

  1. 选择“文件”>“新建项目”。
  2. 在“类别”下面,展开“样例”条目。选择“样例”下面的“企业”,然后单击“企业”条目。
  3. 在“项目”下面,单击 "InterceptorStateless" 条目,然后单击“下一步”按钮。
  4. 在“项目位置”字段中,请为项目文件指定一个文件夹,或者接受缺省值。单击“完成”按钮。
  5. NetBeans IDE 通过其样例项目目录创建了三个项目。所有三个项目都显示在“项目”窗口中。

    样例项目。

    InterceptorStateless-ejb 是生成 .jar 文件的 EJB 模块项目。InterceptorStateless-app-client 是生成 .jar 文件的企业应用程序客户端项目。InterceptorStateless 是生成 .ear 文件的企业应用程序。
  6. 右键单击 "InterceptorStateless",然后从上下文菜单中选择“生成项目”。由于 InterceptorStateless 依赖于其他两个项目,因此也会生成这两个项目。
  7. 右键单击 "InterceptorStateless-ejb",然后从上下文菜单中选择“分析项目”。如果出现一个对话框,询问您要使用的 Java 平台,请选择缺省平台。如果出现一个对话框,询问您是否允许修改项目生成脚本,请单击“确定”。
  8. 在“选择性能分析任务”对话框中,单击“分析性能”按钮。
  9. 单击“整个应用程序”选项。请确保选中“分析应用服务器启动时的性能情况”选项。
  10. 从“过滤器”列表中选择“快速过滤器”,然后单击“快速过滤器”条目旁边的 "..." 按钮,为应进行分析的方法指定过滤器。将显示“设置快速过滤器”窗口。选择“包含”单选按钮。然后,在“过滤器值”文本字段中输入 enterprise.interceptor_stateless_ejb 并单击“确定”按钮。

    “设置快速过滤器”对话框

    将分析 enterprise.interceptor_stateless_ejb 包(及其子包)的类中的所有方法,而不会分析任何其他方法。如果要分析较大的应用程序或 Java EE 组件(如 EJB),则在分析整个应用程序时指定过滤器是非常重要的。否则,Profiler 产生的开销量可能会对性能造成重大影响。
  11. 单击“运行”按钮。如果出现一个对话框,要求您停止捆绑的 Tomcat 服务器,请单击“确定”。IDE 将会花费一段时间在性能分析模式下启动应用服务器、部署样例应用程序,然后执行性能分析。最后,您会在 IDE 的“输出”窗口中看到“生成成功”消息,如下面示例中的突出显示内容一样。

    “生成成功”消息
  12. 在“项目”窗口中,右键单击 "InterceptorStateless" 条目,然后从上下文菜单中选择“运行项目”。IDE 实际上会运行 InterceptorStateless-app-client。这是一个简单的命令行实用程序,它会调用某个 EJB 上的方法,然后报告结果(如下所示)。

    样例输出
  13. 选择“性能分析”>“生成收集结果的快照”。将打开 CPU 结果窗口,如下所示。

    初始结果

    CPU 结果窗口中列出了各种线程;列出的确切名称会随着运行的应用服务器而有所不同。
  14. EJB 方法始终是在应用服务器线程池中选择的线程上调用的。因此,要查看所调用的顶级方法,请展开一个或多个线程,如下所示(单击可查看完整图形)。

    后期的年代数图形。

    在分析您不太熟悉的应用程序时,此方法列表特别有用。通过指定一个包含过滤器可将性能分析限定为应用程序的 EJB 包,您可以方便地查看所调用的顶级方法。在本示例中,NullChecker 类的 checkIfNull() 方法是顶级方法,同样 ArgumentsChecker、NullChecker 和 StatelessSessionBean 类的构造函数也是顶级方法。

  15. 请注意,这些构造函数使用了相对较少的时间,因此,您无需对它们做进一步的了解。但是,对于调查 checkIfNull() 方法所使用的时间却非常有用。要详细了解 checkIfNull() 方法所花费的时间,请展开其下面的条目;如下面的示例所示(单击可查看完整图形)。

    后期的年代数图形。

    由于在过滤器的设置中只包含了 enterprise.interceptor_stateless_ejb 包(及其子包)的类中的方法,因此,此显示中缺少了某些信息。确切地说,不会显示其他包中的方法所花费的时间。

  16. 现在,您已经知道了正在调用的顶级(或“根”)方法,因此就可以修改 Profiler 设置,以便在不产生太多性能分析开销的情况下获取这些方法的详细信息。选择“导航”>“转至类”(或按 Alt+Shift+O 组合键)。在“转至类”对话框的“类名”字段中,输入 NullChecker,然后按 Enter 键。
  17. 将在编辑器中打开 NullChecker.java 文件。将光标放在第 33 行中的任意位置,该行是 checkIfNull() 方法的第一行。

    第 33 行
  18. 选择“工具”>“添加为性能分析根方法”。在“选择设置配置”对话框中,单击“预设:部分应用程序”条目,然后单击“确定”按钮。
  19. 选择“性能分析”>“修改性能分析”。
  20. 将显示“修改性能分析任务”对话框。在其“分析性能”部分中,单击“部分应用程序”选项。
  21. 单击“部分应用程序”选项旁边的“选择”按钮。将显示“指定根方法”对话框,并且仅列出一个方法:checkIfNull()。
  22. 从“过滤器”选项列表中选择“分析所有类”。现在,“分析性能”部分应如下面的示例所示。

    分析性能

    您刚才更改了设置,因此只有一个根方法可以分析。但要注意,NetBeans Profiler 将分析该根方法,并且还会对该方法调用的所有方法执行性能分析。此分析是递归执行的,这样就会分析根方法中的整个调用图形。现在,您已将性能分析限定为仅分析真正所需的方法,并且更改了过滤器,这样就不只是分析 enterprise.interceptor_stateless_ejb 包中的那些方法。
  23. 单击“修改性能分析任务”对话框底部的“确定”按钮。
  24. 在“项目”窗口中,右键单击 "InterceptorStateless" 条目,然后从上下文菜单中选择“运行项目”。
  25. 选择“性能分析”>“生成收集结果的快照”。将打开新的 CPU 结果窗口。
  26. 单击 CPU 结果窗口底部的“热点”标签。该结果应如下面的示例所示(单击可查看完整图形)。

    EJB 热点。

    如果单击包含以前获得的 CPU 结果的窗口中的标签,您可以比较每个窗口中列出的热点。由于以前应用了过滤器,因此先前的快照仅包含了 enterprise.interceptor_stateless_ejb 包中的方法。但要注意的是,为了防止产生过多的性能分析开销,先前使用过滤器是有必要的;通过该过滤器,您可以标识所分析的 EJB 中的所需的顶级方法。在将此方法设置为根方法并删除过滤器时,Profiler 可以提供有关所花时间的完整详细信息;在某些情况下,该时间是指 enterprise.interceptor_stateless_ejb 包之外的方法所花的时间。
  27. 在新的 CPU 结果窗口中,单击 "initUpperCase()" 方法条目,然后单击窗口底部的“组合”标签。该结果应如下面的示例所示(单击可查看完整图形)。

    EJB 的组合结果图。

    您可以方便地看到选定为根方法的 checkIfNull() 与“热点”列表中选择的 initUpperCase() 方法之间的关系。请注意,在“热点”列表中 initUpperCase() 方法被调用了两次。如果查看调用树显示内容,则会发现只调用了一次 initUpperCase() 方法。当分析的代码在应用服务器或 Web 服务器上运行时,经常会出现这种差异;这是因为调用树是按照线程的方式来显示的。而热点是列出的方法以及所有线程对其调用的次数总和。要查找 initUpperCase() 方法的其他调用,请在“调用树”窗口中单击“查找下一个实例”按钮 “查找下一个实例”按钮。“调用树”窗口将突出显示 initUpperCase() 的其他调用,即使是在不同线程上进行的该调用也如此。
  28. 选择“性能分析”>“停止”。

小结:

在本练习中,您学习了如何使用 Profiler 来检查 EJB 方法的性能。您还学习了如何确定根方法,并了解了有关该根方法所调用的方法的详细信息。

返回页首

恭喜您!您已成功地完成了 NetBeans IDE 5.5 Profiler 教程。



后续步骤

您是否还存在性能分析方面的其他问题?请通过 Profiler 常见问题解答获取答案。

要了解有关项目的详细信息,请访问 Profiler 项目主页

Bookmark this page

del.icio.us furl simpy slashdot technorati digg
Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Virtual Box - full virtualizer  Open ESB - The Open Enterprise Service Bus Powered by