Oracle® Developer Studio 12.5:性能分析器教程

退出打印视图

更新时间: 2016 年 6 月
 
 

了解 Java 垃圾收集器行为

该过程介绍如何使用 "Timeline"(时间线)视图以及查看模式设置对 "Timeline"(时间线)的影响,同时检查触发 Java 垃圾收集的活动。

  1. 将查看模式设置为 "User Mode"(用户模式)并在导航面板中选择 "Timeline"(时间线)视图,从而显示此混合 Java/本机应用程序 jsynprog 的执行详细信息。

    image:“User Mode“(用户模式)下的 “Timeline“(时间线)视图

    您应该看到顶部的 "CPU Utilization Samples"(CPU 利用率抽样)条以及三个线程的分析数据。在屏幕抓图中,您可以看到进程 1 以及线程 2、14、15 的数据。您看到的编号和线程数可能取决于 OS、系统以及使用的 Java 版本。

    仅第一个线程(示例中标记为 T:2 的 "Thread 2"(线程 2))将其微状态显示为 "User CPU"(用户 CPU)。其他两个线程花费其所有时间来等待 "User Lock"(用户锁定),这是 JVM 同步的一部分。

  2. 将查看模式设置为 "Expert Mode"(专家模式)。

    "Timeline"(时间线)视图现在应该显示更多线程,尽管用户线程 T:2 看起来几乎未更改。

  3. 使用时间线顶部的垂直缩放控件来调整缩放,从而您可以看到所有线程。

    在以下屏幕抓图中,垂直缩放控件如红色框所示。单击减号按钮来减少线程行的高度,直到您可以看到所有二十个线程。

    image:“Timeline“(时间线)视图中的垂直缩放控件
  4. 单击 "Timeline"(时间线)工具栏中的 "Call Stack Function Colors"(调用堆栈函数颜色)图标 image:调用堆栈函数颜色图标 将函数 Routine.memalloc() 的颜色设置为红色。

    在 "Function Colors"(函数颜色)对话框中,选择 "Legend"(图例)中的 Routine.memalloc() 函数,单击 "Swatches"(色板)中的红色框,然后单击 "Set Selected Functions"(设置所选函数)。

    image:“Timeline“(时间线)视图中用于更改颜色的 “Function Colors“(函数颜色)对话框

    请注意,"Thread 2"(线程 2)在其堆栈顶部具有一个红条。该区域表示 Routine.memalloc() 例程处于运行状态的时间部分。

    您可能需要垂直缩小以查看调用堆栈的更多帧,并水平放大到关注的时间区域。

  5. 使用 "Timeline"(时间线)工具栏中的水平滑块进行足够放大以查看线程 T:2 中的单个事件。

    还可以通过双击或按键盘上的 + 键进行缩放。

    image:放大的 “Timeline“(时间线)视图以查看一行中的三个数据条

    时间线的每行实际包括三个数据条。顶部条表示该事件的调用堆栈。中间条显示黑色勾选标记,其中事件一起过于紧密发生而无法显示所有事件。换句话说,看到勾选标记时,您将知道该空间有多个事件。

    下面的条指示事件状态。对于 T:2,下面的条为绿色,指示正在使用 "User CPU Time"(用户 CPU 时间)。对于线程 3 到 12,下面的条为灰色,指示 "User Lock Time"(用户锁定时间)。

    然而请注意,当用户线程 T:2 处于 Routine.memalloc(显示为红色的例程)中时,线程 3 到线程 12 将具有许多事件聚集在一起同时发生。

  6. 通过执行以下操作,放大到 Routine.memalloc 区域并过滤以仅包括该区域:

    • 单击靠近上面具有红色函数调用的 Routine.memalloc 区域开始处的 T:2 条。

    • 单击并将鼠标拖到靠近该区域末尾,调用堆栈顶部的红色在该处结束。

    • 右键单击并选择 "Zoom"(缩放)-> "To Selected Time Range"(至所选的时间范围)。

    • 在仍选中该范围的情况下,右键单击并选择 "Add Filter: Include only events intersecting selected time range"(添加过滤器:仅包含贯穿所选时间范围的事件)。

    缩放后,您可以看到线程 3-12 中有一些绿色的事件状态,指示 "User CPU"(用户 CPU)时间,并且甚至有几个红色的事件状态,指示 "Wait CPU Time"(等待 CPU 时间)。

  7. 单击线程 3-12 上的任何事件,您在 "Call Stack"(调用堆栈)面板中看到每个线程的事件在堆栈中包括 GCTaskThread::run()

    那些线程表示 JVM 用于运行垃圾收集的线程。GC 线程不会占用大量 "User CPU Time"(用户 CPU 时间),而是仅在用户线程处于 Routine.memalloc 中时运行。

    image:放大到时间线区域
  8. 返回 "Functions"(函数)视图并单击 "Incl.Total CPU"(包含总 CPU)列标题以按包含 "Total CPU Time"(总 CPU 时间)进行排序。

    您应该看到其中一个顶部函数为 GCTaskThread::run() 函数。这样您可以知道用户任务 Routine.memalloc 正在以某种方式触发垃圾收集。

  9. 选择 Routine.memalloc 函数并切换到 "Source"(源)视图。

    image:Routine.memalloc 函数的 “Source“(源)视图

    从源代码的此片段,可以容易地看到为何在触发垃圾收集。该代码分配一个包含一百万个对象的数组并在相同位置存储这些对象的指针,每个对象都进行循环。这将呈现未使用的旧对象,从而其变为垃圾。

继续下一节。