异步和远程请求跟踪
异步任务执行是一种常见的实践,无论是在普通Java代码中,还是在反应式框架中更是如此。源文件中相邻的代码现在在两个或多个不同的线程上执行。对于调试和分析,这些线程变化带来了两个问题:一方面,不清楚调用操作的开销有多大。另一方面,无法将昂贵的操作追溯到导致其执行的代码。
JProfiler根据调用是否留在同一个JVM中提供不同的解决方案。如果异步执行发生在调用它的同一个JVM中,“内联异步执行”调用树分析计算出一个包含调用点和执行站点的单一调用树。如果请求发送到远程JVM,调用树包含指向调用点和执行站点的超链接,因此您可以在显示涉及JVM的分析会话的不同JProfiler顶级窗口之间无缝导航。
启用异步和远程请求跟踪
异步机制可以通过多种方式实现,无法以通用方式检测在单独线程或不同JVM上启动任务的语义。JProfiler明确支持几种常见的异步和远程请求技术。您可以在请求跟踪设置中启用或禁用它们。默认情况下,请求跟踪未启用。还可以在会话启动对话框中配置请求跟踪,该对话框在会话启动之前直接显示。
在JProfiler的主窗口中,状态栏指示是否启用了某些异步和远程请求跟踪类型,并为您提供配置对话框的快捷方式。
JProfiler检测到在被分析的JVM中使用了未激活的异步请求跟踪类型,并在状态栏中的异步和远程请求跟踪图标旁边显示一个
异步跟踪
如果至少激活了一种异步跟踪类型,CPU、分配和探针记录的调用树和热点视图将显示有关所有激活的跟踪类型的信息,并带有一个计算“内联异步执行”调用树分析的按钮。在该分析的结果视图中,所有异步执行的调用树通过一个
在另一个线程上卸载任务的最简单方法是启动一个新线程。使用JProfiler,您可以通过激活“线程启动”请求跟踪类型来跟踪线程从创建到执行站点的过程。然而,线程是重量级对象,通常用于重复调用,因此这种请求跟踪类型更适合调试目的。
在其他线程上启动任务的最重要和通用的方法是使用java.util.concurrent
包中的执行器。执行器也是许多处理异步执行的高级第三方库的基础。通过支持执行器,JProfiler支持处理多线程和并行编程的整个类库。
除了上述通用情况,JProfiler还支持JVM的两个GUI工具包:AWT和SWT。两个工具包都是单线程的,这意味着有一个特殊的事件调度线程可以操作GUI小部件并执行绘图操作。为了不阻塞GUI,长时间运行的任务必须在后台线程上执行。然而,后台线程通常需要更新GUI以指示进度或完成。这是通过安排一个Runnable
在事件调度线程上执行的特殊方法来完成的。
在GUI编程中,您经常需要跟踪多个线程更改以连接原因和结果:用户在事件调度线程上启动一个操作,该操作又通过执行器启动后台操作。完成后,该执行器将一个操作推送到事件调度线程。如果最后一个操作造成性能问题,它距离原始事件有两个线程更改。
最后,JProfiler支持Kotlin协程,Kotlin的多线程解决方案为所有Kotlin后端实现。异步执行本身是启动协程的点。Kotlin协程的调度机制是灵活的,实际上可以涉及在当前线程上启动,在这种情况下,“异步执行”节点有一个内联部分,然后在节点文本中单独报告。
挂起的方法可以中断执行,然后可能在不同的线程上恢复。检测到挂起的方法有一个额外的
跟踪未分析的调用点
默认情况下,执行器和Kotlin协程跟踪仅跟踪调用点位于被分析类中的异步执行。这是因为框架和库可以以与您自己的代码执行无直接关系的方式使用这些异步机制,添加的调用和执行站点只会增加开销和干扰。然而,跟踪未分析的调用点也有用例。例如,框架可以启动一个Kotlin协程,然后在其上执行您自己的代码。
如果检测到未分析类中的此类调用点,调用树和热点视图中的跟踪信息会显示相应的通知消息。在实时会话中,您可以直接从这些视图中分别为执行器和Kotlin协程跟踪启用未分析调用点的跟踪。这些选项可以随时在会话设置对话框的“CPU分析”步骤中更改。
重要的是要理解,Kotlin协程只能在其启动时CPU记录处于活动状态时进行跟踪。如果您稍后开始CPU记录,Kotlin协程的异步执行将无法内联。JProfiler会像检测未分析类中的调用点一样通知您。如果您需要分析在应用程序开始时启动的长寿命协程,则使用附加模式不是一个选项。在这种情况下,使用-agentpath VM参数启动JVM,并在启动时开始CPU记录。
远程请求跟踪
对于选定的通信协议,JProfiler能够插入元数据并跨JVM边界跟踪请求。支持的技术有:
- HTTP:客户端侧的HttpURLConnection、java.net.http.HttpClient、Apache Http Client 4.x、Apache Async Http Client 4.x、OkHttp 3.9+,服务器侧的任何Servlet-API实现或不带Servlets的Jetty
- 额外支持异步JAX-RS调用,适用于Jersey Async Client 2.x、RestEasy Async Client 3.x、Cxf Async Client 3.1.1+
- Web服务:JAX-WS-RI、Apache Axis2和Apache CXF
- RMI
- gRPC
- 远程EJB调用:JBoss 7.1+和Weblogic 11+
为了能够在JProfiler中跟踪请求,您必须分析两个VM并在不同的JProfiler顶级窗口中同时打开它们。这适用于实时会话和快照。如果目标JVM当前未打开,或者在远程调用时CPU记录未激活,单击调用点超链接将显示错误消息。
在跟踪远程请求时,JProfiler在涉及的JVM的调用树中明确显示调用点和执行站点。JProfiler中的调用点是记录的远程请求执行之前的最后一个被分析的方法调用。它在位于不同VM的执行站点启动任务。JProfiler允许您通过调用树视图中显示的超链接在调用点和执行站点之间跳转。
对于所有线程,调用点在远程请求跟踪方面具有相同的身份。这意味着当您从调用点跳转到执行站点或反之时,没有线程解析,跳转总是激活“所有线程组”以及“所有线程状态”线程状态选择,以确保目标是显示树的一部分。
调用点和执行站点之间是1:n关系。一个调用点可以在多个执行站点启动远程任务,尤其是如果它们位于不同的远程VM中。在同一个VM中,单个调用点的多个执行站点不太常见,因为它们必须在不同的调用栈中发生。如果一个调用点调用多个执行站点,您可以在对话框中选择其中一个。
执行站点是调用树中的一个合成节点,包含由一个特定调用点启动的所有执行。执行站点节点中的超链接将您带回到该调用点。
如果同一个调用点重复调用同一个执行站点,执行站点将显示其所有调用的合并调用树。如果不希望这样,您可以使用异常方法功能进一步拆分调用树,如下图所示。
与仅从单个调用点引用的执行站点不同,调用点本身可以链接到多个执行站点。通过调用点的数字ID,您可以识别相同的调用点,如果您看到它从不同的执行站点引用。此外,调用点显示远程VM的ID。被分析VM的ID可以在状态栏中看到。它不是JProfiler内部管理的唯一ID,而是一个显示ID,从一开始,每打开一个新的被分析VM就递增。