目标

使用 IBM Thread Analyzer 工具分析 AEM Java 线程转储。

步骤

  1. 下载并安装 IBM Thread Analyzer(我们将其简称为 IBM TDA)
  2. 从遇到性能问题的 AEM 实例中捕捉线程转储
  3. 在 IBM TDA 中打开线程转储。
  4. 要查看某个线程转储的详细信息,请在列表中选择该文件,然后单击“Thread Detail”(线程详细信息)按钮*。
tda-threaddetail
  1. 按“Stack Depth”(堆栈深度)进行排序,使最长的堆栈排在顶部。
tda-image1
  1. 查看堆栈深度为 10 行或更长的线程。这些通常就是最为重要的线程。记下相关的线程。
  2. 按线程“State”(状态)进行排序。
  3. 向下滚动到“Runnable”(可运行)线程。可运行线程是在获取线程转储时主动占用 CPU 时间的线程。

注意:在查看“Runnable”(可运行)线程时,可以忽略此页面底部可忽略线程部分列出的线程。

  1. 找到属于此应用程序的可运行线程,例如,后台作业线程或请求线程(请求线程的名称如下所示:127.0.0.1 [1347028187737] GET /content/sites/global/en/sitemap.static-delivery.httpd.html HTTP/1.1)。找到后,逐个单击这些线程。
  2. 对于每个请求线程,可通过查看线程名称中的时间戳来确定用户浏览器向服务器发出请求的时间。例如,在上述线程名称中,时间戳(毫秒,unix epoch 格式)为 1347028187737。我们可以通过 www.epochconverter.com 将该 epoch 数字转换为日期/时间。每个线程转储显示获取时的日期和时间。您可以计算请求时间和线程转储时间之间的时间差,以便确定请求处于活动状态的时间。
  3. 查看请求线程后,滚动浏览其他“Runnable”(可运行)线程。找到相关的“Runnable”(可运行)线程后,即会显示中间面板“Waiting threads”(等待线程)。此处列出的线程正在等待选定线程释放监视器。如果没有看到任何等待线程,则您选择的线程可能还是 Lock 的所有者(有关详细信息,请参阅 Lock 的实现类)。例如,对于 ReentrantReadWriteLock,无法确定哪个线程是锁持有者,因为锁在内部实施了多个监视器。因此,您可能必须查看源代码以将其与可能是锁持有者的线程进行匹配。
  4. 如果线程拥有多个其他线程在等待其完成的锁或监视器,则完成其余的线程转储,以确定是否可以找到存在相同问题的其他线程。查看同一线程是否还存在于其他转储中(在 IBM TDA 中,可以选择多个线程转储并单击“Compare Threads”(比较线程)按钮*以查看跨多个线程转储的线程的状态)。
tda-comparethreads
  1. 查看以下截图中的收集器服务:
tda-Image2
  1. 在此视图中,您可以查看跨多个线程转储的线程以确定它是否为长期运行的线程。基本上,如果跨多个转储的线程状态为“Runnable”(可运行),并具有长堆栈,则通常意味着它是长期运行的线程。
  2. 如果未找到可运行线程,则请转回到线程列表,选择线程转储,然后单击顶部面板上的“Monitor Detail”(监控器详细信息)按钮*。IBM TDA 将打开一个窗口,显示拥有线程及等待线程的监视器树视图。注意:该树视图可能会显示一些线程池线程,如 Servlet 引擎线程池监视器,而空闲线程可能会被忽略。通常,您可以确定线程是否是空闲线程池线程,因为大多数情况下,它们只有 10 或更少的堆栈行。
tda-monitordetail
  1. 在顶部面板上,单击“Find long-running threads”(查找长期运行的线程)按钮(此按钮拥有一个望远镜图标)。
  2. 在左下角,现在应会在线程转储后面看到一个新图标。单击此图标将显示所有长期运行的线程。
  3. 在右侧窗格中再次按“State”(状态)进行排序。
  4. 向下滚动到可运行的线程,以查找在整个转储中处于运行状态的线程。
线程级别 CPU 利用率(仅限 Linux 平台):
  1. 如果除线程转储之外,还捕捉“top -H -b -n1 -p <javapid>”输出,则可以交叉引用线程级别的 CPU 利率率。打开 top 输出,并获取正在使用 CPU 的线程的进程 ID。将该进程 ID 转换为十六进制值,然后在对应的线程转储文件中搜索该十六进制值。该 ID 应与其中一个线程的“nid”相匹配。
  2. 如果使用大部分 CUP 的匹配线程是“VM 线程”或任何“GC”线程,则表示可能存在内存问题。对其他线程转储和 top 输出重复执行该操作,如果存在此类占用 CPU 时间的线程,则说明存在内存问题。
  3. 如果已确定存在内存问题,则在下一次出现问题时捕捉堆转储。有关捕捉和分析堆转储的更多详细信息,请参阅本文

可忽略线程:

  • VM 线程:这是虚拟机系统线程。
  • 以 GC 任务线程开始的线程:这些是垃圾收集线程。
  • 名称与代码中 java.net.PlainSocketImpl.socketAccept(Native Method) 处的 [1347028691218] 相似的线程:这些是 Servlet 引擎线程池中等待新连接的线程。

本产品经 Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License 许可  Twitter™ 与 Facebook 中的内容不在 Creative Commons 的条款约束之下。

法律声明   |   在线隐私策略