如何在Java Web应用程序在Tomcat中运行中找到热点?

问题描述

我有一个Web应用程序花费的时间比执行特定任务所需的时间长。我使用并发性为a的ab将Web应用程序置于负载下,并且我看到tomcat使用了100%的一个cpu。我想深入研究该应用程序,并回答以下问题:“此Java代码做什么使Java代码消耗100%的cpu?”。

我尝试如下使用Java Flight Recorder来记录我的应用程序,如下所示:

-sh-4.1$ jcmd 115388 JFR.start duration=60s filename=/tmp/app-service-live.jfr settings=profile

生成的JFR文件加载到VisualVM中可以得到以下信息:

Screenshot of VisualVM CPU samples tab

从屏幕快照中可以看到,尽管在录制时只有一个线程处于高温状态,但所有线程都被标记为高温。深入研究其中一个红色的热线程,VisualVM将我们报告为在sun.misc.Unsafe.park()方法内部正在燃烧。这种方法不是炽热,而是石头冷。

无法分辨造成100%cpu占用的热代码与等待外部事件而阻塞的冷代码间的区别,没有出现连贯的画面。

我需要对jcmd命令行进行哪些更改才能正确捕获cpu在做什么?

在消除冷代码的同时,我需要在VisualVM中遵循哪些替代过程来查找热代码

解决方法

我还没有看到Visual VM的实现,但是在CPU上采样的事件称为jdk.ExecutionSample。

还有一个jdk.NativeMethodSample事件,该事件可用于查找卡在本机中的线程,但是JVM无法确定它们是否正在运行,因此它们不应成为可视化的一部分

如果是这样,则可以使用JDK Mission Control来解决该错误,或​​者更改配置以使该事件不会被记录。在JAVA_HOME / lib / jfr目录中查找并将default.jfc复制到一个新文件,即my.jfc,然后更改为该文件,以便jdk.NativeMethodSample事件具有以下设置:

Here is the ID:  {'ID': 'E'}
Here is StartTime: 06:30:00
Here is EndTime: 14:30:00
Here is Description: Early

然后像这样运行它:

<setting name="enabled">false</setting>

您还可以将配置复制到另一个目录,但是随后您必须指定完整路径:

$ jcmd <pid> settings=my duration=60s ...