在命令行中对正在运行的Java应用程序进行性能分析

61

我经常用VisualVM对Java应用程序进行性能分析,但需要在机器上安装X才能运行。

我知道可以通过管理端口连接,但那只是离线采样的性能分析,对我来说不够。

因此,我正在寻找一种解决方案,可以通过命令行对运行中的Java应用程序方法的CPU使用情况进行性能分析。收集数据后,我可以在另一台机器上分析所收集的数据。

更新:

看起来我需要更具体一些。我想从命令行对运行中的Java应用程序进行性能分析,而不是停止并重新运行它。


2
你可以使用 jstack 收集10或20个堆栈采样吗? 如果 Foo 是一个方法,那么它的总时间使用率就是包含它的采样的比例。 它的CPU使用率是不以I / O或系统调用终止的采样中具有该方法的采样的比例。它的“自身时间”是指以它自己作为终点的采样的比例。 - Mike Dunlavey
这会和VisualVM的离线分析类似,对吧? - KARASZI István
1
请查看文档:http://visualvm.java.net/profiler.html。它无法告诉你每行代码(而不是函数)所占的总时间百分比(而不是独占时间),以及整体时间(而不仅仅是CPU)。它存在这些问题:https://dev59.com/xHI-5IYBdhLWcg3wlpeW#1779343。堆栈采样并不美观,但它可以快速找到性能问题。其他工具可能更漂亮,它们会给你很多数字让你去研究,但它们不能直接带你找到问题,无论它是什么。 - Mike Dunlavey
我尝试获取堆栈跟踪,但它拒绝在没有“-F”标志的情况下运行,而使用该标志会导致我的应用程序冻结。 - KARASZI István
嘿,我不需要任何漂亮的东西。我要么在IDE下运行它并以这种方式收集它们,要么使用类似jstack的工具对正在运行的应用程序进行堆栈快照。 - Mike Dunlavey
@Mike,你能把你的评论发表为一个答案吗?我会接受它! - KARASZI István
7个回答

33

jvmtop应用程序是一种方便的命令行分析工具。无需停止JVM。使用方法:

jvmtop.sh --profile <PID>

会输出像这样的内容,这些内容将在应用程序运行时更新:

  Profiling PID 24015: org.apache.catalina.startup.Bootstrap
  36.16% (    57.57s) hudson.model.AbstractBuild.calcChangeSet()
  30.36% (    48.33s) hudson.scm.SubversionChangeLogParser.parse()
   7.14% (    11.37s) org.kohsuke.stapler.jelly.JellyClassTearOff.parseScript()
  ...

优点是它不需要使用仪器。将要被分析的JVM类不会被更改。

如果您正在寻找更加直观的东西,请查看基于jvmtop的jvm-mon


4
多年来,我一直在使用并抱怨visualvm。感谢您向我介绍了这个方便的工具。它无需使用JVM代理、服务器重启等操作即可运行。只需将其解压到您想分析的电脑上,将JAVA_HOME设置为正确的位置并运行即可。 - Jilles van Gurp
6
这是一款优秀的工具,但这个项目好像已经停滞不前了。自2015年以来没有任何更新发布。 - user1870400
jvm-mon是一个次优的工具,分析应该包括堆栈跟踪。 - peterh
2
似乎自JDK 9以来,jvmtop已经无法使用了。 - Rok Povsic
有人已经更新到Java 11,但它仍然不能在Java 17中使用。 - mjaggard

27

看起来在命令行中对Java应用程序进行分析的“内置”方法是使用分析命令行参数启动它,就像这样

$ java -Xrunhprof:cpu=samples,file=myprogram.hprof ...

然后,使用一些GUI工具(或Web服务器工具,如jhat)或命令行工具检查文件“myprogram.hprof”,在进程退出后(并且在那时创建文件)。如果使用了“QUIT”信号技巧(提到https://dev59.com/QXE95IYBdhLWcg3wXcrd#2344436),则可以在不退出JVM的情况下随意生成文件(它似乎会附加到上一个输出文件)。或者等待进程退出,它将生成该文件。这个(内置的)分析器很少进行采样,因此通常整体影响较小。参考:http://web.archive.org/web/20160623224137/https://thunderguy.com/semicolon/2004/04/18/profiling-a-java-program-easily/

您也可以使用“穷人的分析器”,通过收集大量的jstack并将它们转储到例如flamegraph或其他分析器/聚合器中来完成。


3
感谢指引!给未来的读者注意:hprof 采样处于 Java RUNNABLE 状态的线程(因此它不等同于聚合多个 jstack 转储,就像我预期的那样,但它也不测量 CPU 消耗)。它有其他需要注意的地方 - 参见 http://www.brendangregg.com/blog/2014-06-09/java-cpu-sampling-using-hprof.html。 - Nickolay

15

你能使用 jstack 收集10或20个堆栈样本吗?然后,如果 Foo 是一个方法,它的总时间使用率是包含它的样本的分数。它的 CPU 使用率是那些不以 I/O 或系统调用终止的样本的分数。它的“自身时间”是它本身是终点的样本的分数。

我不需要任何漂亮的东西。我要么在 IDE 下运行它并以这种方式收集它们,要么使用像 jstack 这样的东西快照正在运行的应用程序的堆栈。

这就是随机暂停技术。


1
我选择了这个想法:http://svn.apache.org/repos/asf/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/Profiler.java - KARASZI István
这个解决方案帮助我找到了服务器DNS解析的瓶颈。再次感谢! - KARASZI István
@KARASZI István:很高兴能帮到你。 - Mike Dunlavey

7

最精确的剖析可通过https://github.com/jvm-profiling-tools/async-profiler实现。

该项目是一个Java的低开销采样剖析器,不会受到安全点偏差问题的影响。它具有HotSpot特定的API,用于收集堆栈跟踪和跟踪内存分配。该剖析器可与OpenJDK、Oracle JDK以及基于HotSpot JVM的其他Java运行时一起使用。

这是我安装并从命令行运行它的脚本:

async-profiler.sh

if [ ! -d profiler ]; then
  mkdir profiler && cd profiler && curl -L https://github.com/jvm-profiling-tools/async-profiler/releases/download/v1.6-ea/async-profiler-1.6-ea-linux-x64.tar.gz | tar xvz
  echo 1 > /proc/sys/kernel/perf_event_paranoid
  echo 0 > /proc/sys/kernel/kptr_restrict
  #apt install openjdk-8-dbg
else
  cd profiler
fi

#jps

./profiler.sh -d 60 -f dump_`date +%Y-%m-%d_%H-%M-%S`.jfr `jps -q`

假设应用程序在同一用户下运行,并有单个Java进程PID需要由jps列出。

剖析持续时间为60秒。

无需修改应用程序的启动选项或重新启动应用程序。

IntelliJ IDEA Ultimate内置了用于检查转储的GUI:https://www.jetbrains.com/help/idea/cpu-profiler.html


使用 async-profiler 进行 Java 应用程序性能分析的精美插图文章:https://hackernoon.com/profiling-java-applications-with-async-profiler-049s2790 - Vadzim
另一个简介:https://www.baeldung.com/java-async-profiler - undefined

6

但我真的不明白如何将其附加到PID。 - KARASZI István
1
抱歉,据我所知,hprof 不允许附加到进程。你最好去了解像 jprofile 和 jtop 这样的工具。http://java.sun.com/developer/technicalArticles/J2SE/monitoring/ - Sanjay T. Sharma
@SanjayT.Sharma 我正在使用HPROF进行CPU分析,通过cpu=times生成应用程序每次运行后的数据,但我无法分析哪个进程在特定运行中具有最大的CPU使用率。使用jhat并没有帮助太多,请指点。 - Manas Pratim Chamuah
很抱歉要点踩,但所有的java.sun.com链接都已失效。javalobby.org的链接仍然有效 :) - blong
1
@blong:好眼力,已修复损坏的链接。 - Sanjay T. Sharma
1
@SanjayT.Sharma,太好了,非常感谢!将踩转为赞 :) - blong

3

对于“已启动”的JVM,一种分析性能的方法是聚合多个不同时刻获取的jstack。

例如,您可以将它们解析并显示为FlameGraph(有关详细信息,请参见该链接的各个答案,我这里不会重复包含)。


1
你可以远程运行大多数商业分析工具,因此代理程序在服务器上运行,然后通过开发机器上的客户端连接到该代理程序。我个人最喜欢的分析工具是JProfiler。它的购买价格相当合理,而且非常稳定(这并非所有商业分析工具都有的特点)。

http://www.ej-technologies.com/products/jprofiler/overview.html

其他商业分析工具稳定可靠,但不是我最喜欢的,例如YourKIT。

http://www.yourkit.com/

那些较小的供应商制造了很好的工具。这些工具将为您提供有关方法计时、内存使用、GC等方面的大量信息,比jconsole更多。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接