JVM的CPU使用率如何测量:Java代码

13

有没有一种跨平台的方式来测量JVM(一旦启动Java应用程序)的CPU使用情况(Windows + Unix + Mac)?我已经使用过Jconsole,但我需要的是一段Java代码,而不是一个可以监视CPU利用率的工具。我已经尝试过

ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage()

我正在使用JMX,但它并没有帮助我获得我需要的JVM特定的CPU使用情况(例如在启动服务器时),而不是系统的平均负载。

7个回答

9

您应该查看来自Thread MBean的ThreadMXBean.getThreadCPUTime()方法。

线程CPU时间

Java虚拟机实现可能支持测量当前线程、任何线程或无线程的CPU时间。

还有JDK中的JTop示例应用程序jdk\demo\management\JTop\src\JTop.java此处。请查看:

/**
 * Get the thread list with CPU consumption and the ThreadInfo for each thread
 * sorted by the CPU time.
 */
private List<Map.Entry<Long, ThreadInfo>> getThreadList()

嗨,可以使用ThreadMXBean.getCurrentCPUTime()方法获取JVM的CPU使用率(以百分比表示)吗? - nadh
1
你需要计算所有线程的CPU时间总和才能得到总CPU时间。我认为总和可能会有些偏差,因为你无法原子地查询所有线程的CPU时间。 - Thomas Jung

2

在任何时刻,一个线程要么正在运行(占用100%的核心),要么不在运行状态(占用0%)。 没有中间状态。 你需要的是对线程运行状态进行短期快照,并在这些快照上计算平均值。


你能详细说明一下吗?难道你不需要考虑被阻塞或处于timed_waiting状态的线程吗?我曾经看到过timed_waiting线程有时会占用CPU周期。我的要求是当CPU使用率超过阈值时,触发JVM生成更多的线程转储,以便我们可以调查问题。 - Andy Dufresne

2

From here

    com.sun.management.OperatingSystemMXBean operatingSystemMXBean = 
         (com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
    int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
    long prevUpTime = runtimeMXBean.getUptime();
    long prevProcessCpuTime = operatingSystemMXBean.getProcessCpuTime();
    double cpuUsage;
    try 
    {
        Thread.sleep(500);
    } 
    catch (Exception ignored) { }

    operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    long upTime = runtimeMXBean.getUptime();
    long processCpuTime = operatingSystemMXBean.getProcessCpuTime();
    long elapsedCpu = processCpuTime - prevProcessCpuTime;
    long elapsedTime = upTime - prevUpTime;

    cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * availableProcessors));
    System.out.println("Java CPU: " + cpuUsage);

我尝试了这个方法,但似乎没有给出准确的值。与我在jconsole中查看的相比,当CPU使用率已经达到99%时,计算结果为65%。有没有Java替代方案? - Andy Dufresne

1
你可以尝试使用 https://github.com/mvysny/webmon。只需将webmon-analyzer jar添加到您的项目中,即可启动采样器和TCP / IP服务器。采样器将轮询JMX API并将统计数据保存一段时间,然后您只需telnet localhost 5455即可获取这些统计数据的文本转储。非常适合生产环境。免责声明:我是作者,该项目有点老。

1

Java本身不提供此功能。有几个开源API可用于测量CPU使用情况。
我推荐Sigar API。除了CPU使用率外,您还可以获得更多其他功能,例如内存使用情况、系统正常运行时间等。


这不是正确的,因为自Java 1.5以来,ThreadMXBean.getCurrentCPUTime()被引入,参见@thomas-jung的答案。但Sigar确实具有一些有趣的功能。 - Ed Griebel
SIGAR 可能会导致 JVM 崩溃并使一切都崩溃。即使它是间歇性的,我认为在生产中你也无法承受这种情况。 - AKS

1

也许 this 或类似的库可以帮助你。


0

使用纯Java编程查询CPU使用率是不可能的。这方面没有API可用。一个建议的替代方法可能会使用Runtime.exec()来确定JVM的进程ID(PID),调用外部的、特定于平台的命令,如ps,并解析其输出以获取所需的PID。

请参阅此链接


1
这是不正确的,因为自Java 1.5以来引入了ThreadMXBean.getCurrentCPUTime(),请参见@Thomas-jung的答案。此外,链接的文章是2002年的。 - Ed Griebel

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