问题描述
我有一个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中可以得到以下信息:
从屏幕快照中可以看到,尽管在录制时只有一个线程处于高温状态,但所有线程都被标记为高温。深入研究其中一个红色的热线程,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 ...