在命令行中分析正在运行的 Java 应用程序

Posted

技术标签:

【中文标题】在命令行中分析正在运行的 Java 应用程序【英文标题】:Profiling a running Java application in command line 【发布时间】:2011-10-14 08:00:58 【问题描述】:

我经常使用 VisualVM 分析运行 Java 应用程序,但它需要 X 才能在机器上运行。

我知道我可以通过管理端口进行连接,但这将是一个离线采样分析,这对我来说还不够。

所以我正在寻找一种解决方案,通过它我可以从命令行分析正在运行的 Java 应用程序的方法的 CPU 使用率。我在服务器上收集数据就足够了,然后可以在不同的机器上分析收集到的数据。

更新:

看来我需要更具体一些。我想从命令行分析一个正在运行的 Java 应用程序,我不想停止它并重新运行它。

【问题讨论】:

你能用 jstack 收集 10 或 20 个堆栈样本吗?那么如果 Foo 是一个方法,它的总时间使用是包含它的样本的一部分。它的 CPU 使用率是那些不以 I/O 或系统调用终止的样本的一部分。它的“自身时间”是它本身是终点的样本的一部分。 这和 VisualVM 离线分析是一样的,不是吗? Check the doc. 它不会按行(不是函数)告诉您该行负责的包含时间(非独占)百分比,以及总时间(不仅仅是 CPU)。它受到these problems 的影响。堆栈采样并不漂亮,但它很快就发现了性能问题。其他工具很漂亮,它们会给你很多数字来解决问题,但它们并不能直接带你解决问题,不管它是什么。 我试图获取堆栈跟踪,但它拒绝在没有 -F 标志的情况下运行,它会冻结我的应用程序。 嘿,我不需要漂亮的东西。我要么在 IDE 下运行它并以这种方式收集它们,要么使用 jstack 之类的东西来快照正在运行的应用程序的堆栈。 【参考方案1】:

我们在服务器上使用了hprof,如果您无法运行完整的 VisualVM 会话,它肯定比 sysouts 更好。

使用 hprof 的例子很多:

http://www.javalobby.org/java/forums/t19612.html https://coderwall.com/p/il3h4g/easy-profiling-java-from-command-line http://www.brendangregg.com/blog/2014-06-09/java-cpu-sampling-using-hprof.html

【讨论】:

但我真的不明白如何将它附加到 pid 抱歉,AFAIK,hprof 不允许附加到进程。你最好的选择是研究像 jprofile 和 jtop 这样的工具。 java.sun.com/developer/technicalArticles/J2SE/monitoring @SanjayT.Sharma 我正在使用 HPROF 通过使用 cpu=times 进行 CPU 分析,并在每次特定运行应用程序后生成数据,但我无法分析数据,例如哪个进程一个特定的运行有最大 cpu 使用率。使用 jhat 并没有多大帮助,请启发。 @blong:好地方,修复了损坏的链接。 @SanjayT.Sharma ,太好了,非常感谢! Downvote 转换为 upvote :)【参考方案2】:

您可以远程运行大多数商业分析器,以便在服务器上运行代理,然后通过您的开发机器上的客户端连接到该代理。我最喜欢的分析器是 JProfiler。这是相当合理的购买,而且非常稳定(并非所有商业分析器都是如此)。

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

YourKIT 是其他稳定但不是我最喜欢的商业分析器。

http://www.yourkit.com/

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

【讨论】:

【参考方案3】:

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

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

这就是random-pause 技术。

【讨论】:

我选择了这个想法:svn.apache.org/repos/asf/jackrabbit/sandbox/jackrabbit-j3/src/… 这个解决方案帮助我找到了服务器上 DNS 解析的瓶颈。再次感谢您! @KARASZI István:很高兴它有帮助。【参考方案4】:

看起来从命令行分析 java 应用程序的“内置”方法是使用分析命令行参数启动它,像这样

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

然后在进程退出后(此时文件已创建),使用一些 GUI 工具(或 Web 服务器工具,如 jhat)或 command line tool 检查文件“myprogram.hprof”。

如果您使用https://***.com/a/2344436/32453 提到的“QUIT”信号技巧,那么您可以在不退出 JVM 的情况下随意生成文件(它似乎附加到前一个输出文件)。或者等到进程退出再生成文件。

此(内置)分析器不经常进行采样,因此总体上通常会降低减速/影响。

参考:http://web.archive.org/web/20160623224137/https://thunderguy.com/semicolon/2004/04/18/profiling-a-java-program-easily/

您也可以通过收集大量 jstack 并将它们转储到 ex: flamegraph 或其他一些分析器/聚合器中来执行“穷人的分析器”...

【讨论】:

感谢指点!给未来读者的注意事项:hprof 是在 Java RUNNABLE 状态下对线程进行采样(所以它不等同于聚合多个 jstack 转储,就像我预期的那样,但它也不测量 CPU 消耗)。它还有其他问题 - 请参阅 brendangregg.com/blog/2014-06-09/…【参考方案5】:

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

【讨论】:

多年来我一直在搞乱和诅咒visualvm。感谢您向我指出这个方便的工具。无需 JVM 代理、服务器重启等即可工作。只需解压您要分析的框,将 JAVA_HOME 指向正确的位置并运行。 这是一个很棒的工具,但是这个项目看起来已经死了。自 2015 年以来没有发布 jvm-mon 是一个......次优工具,分析应该也意味着堆栈跟踪。 自 JDK 9 以来 jvmtop 似乎不再工作了。【参考方案6】:

分析“已启动”JVM 的一种方法是聚合多个 jstacks。

例如,您可以将它们解析并显示为 FlameGraph(请参阅该链接的各种答案中的详细信息,我不会在此处重复包含它们)。

【讨论】:

【参考方案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`

假设应用程序在同一用户下运行,并且 jps 列出了一个 java 进程 PID。 分析持续时间为 60 秒。

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

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

【讨论】:

关于 async-profiler 的精美插图文章:hackernoon.com/…

以上是关于在命令行中分析正在运行的 Java 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

在生产环境中分析正在运行的 ASP.NET 应用程序

在 Java 中分析本机方法 - 奇怪的结果

在 Eclipse 中分析 Java 应用程序的最佳方法是啥?

如何查看 JVM(?)内部。我可以在工作应用程序中分析方法、参数、返回值等吗?

在Firefox中分析Webworkers

想要在本地机器的 JBoss 服务器中分析 Web 应用程序