如何检查 Java 中的 CPU 和内存使用情况?

Posted

技术标签:

【中文标题】如何检查 Java 中的 CPU 和内存使用情况?【英文标题】:How do I check CPU and Memory Usage in Java? 【发布时间】:2010-09-09 15:14:05 【问题描述】:

我需要在java中检查服务器的CPU和内存使用情况,有人知道怎么做吗?

【问题讨论】:

也许这些链接会有所帮助:javaworld.com/javaworld/javaqa/2002-11/01-qa-1108-cpu.htmlroseindia.net/javatutorials/… Using Java to get OS-level system information 的可能副本 【参考方案1】:

如果你在 JVM 中专门寻找内存:

Runtime runtime = Runtime.getRuntime();

NumberFormat format = NumberFormat.getInstance();

StringBuilder sb = new StringBuilder();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();

sb.append("free memory: " + format.format(freeMemory / 1024) + "<br/>");
sb.append("allocated memory: " + format.format(allocatedMemory / 1024) + "<br/>");
sb.append("max memory: " + format.format(maxMemory / 1024) + "<br/>");
sb.append("total free memory: " + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024) + "<br/>");

但是,这些只能作为估计......

【讨论】:

那么如果我在 Eclipse 中运行,这将取决于我的 Eclipse 设置? 请注意,这不是实际使用的内存——这是“分配的内存”,这意味着 java 已分配的堆,所以如果你有 -Xms90g 并且你的应用程序非常轻量级,你会仍然会分配大于 90g 的内存。请参阅下面已删除的“未知(雅虎)”的答案(乍一看可能有所不同) 只是好奇,为什么这些只是估计值? @ComputerScientist 因为 free 实际上是免费的(GC 后),所以它不会显示等待 GC 的对象。为了更准确,请在此答案之前运行 2 次垃圾收集。如果您尝试使用和不使用 GC,您会发现 GC 后的值非常一致,但 preGC 通常至少是这些值的两倍。 @sbeliakov 您可以使用 JavaSysmon (github.com/jezhumble/javasysmon),尽管我建议您打开一个新问题,我会回答它。 GitHub 上的库有一个错误,将 32 位识别为 64 位,但我发现了一个混合不同 jar 的工作 [github.com/goxr3plus/XR3Player/blob/master/resources/libs/…]。【参考方案2】:
import java.io.File;
import java.text.NumberFormat;

public class SystemInfo 

    private Runtime runtime = Runtime.getRuntime();

    public String info() 
        StringBuilder sb = new StringBuilder();
        sb.append(this.osInfo());
        sb.append(this.memInfo());
        sb.append(this.diskInfo());
        return sb.toString();
    

    public String osName() 
        return System.getProperty("os.name");
    

    public String osVersion() 
        return System.getProperty("os.version");
    

    public String osArch() 
        return System.getProperty("os.arch");
    

    public long totalMem() 
        return Runtime.getRuntime().totalMemory();
    

    public long usedMem() 
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    

    public String memInfo() 
        NumberFormat format = NumberFormat.getInstance();
        StringBuilder sb = new StringBuilder();
        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        sb.append("Free memory: ");
        sb.append(format.format(freeMemory / 1024));
        sb.append("<br/>");
        sb.append("Allocated memory: ");
        sb.append(format.format(allocatedMemory / 1024));
        sb.append("<br/>");
        sb.append("Max memory: ");
        sb.append(format.format(maxMemory / 1024));
        sb.append("<br/>");
        sb.append("Total free memory: ");
        sb.append(format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024));
        sb.append("<br/>");
        return sb.toString();

    

    public String osInfo() 
        StringBuilder sb = new StringBuilder();
        sb.append("OS: ");
        sb.append(this.osName());
        sb.append("<br/>");
        sb.append("Version: ");
        sb.append(this.osVersion());
        sb.append("<br/>");
        sb.append(": ");
        sb.append(this.osArch());
        sb.append("<br/>");
        sb.append("Available processors (cores): ");
        sb.append(runtime.availableProcessors());
        sb.append("<br/>");
        return sb.toString();
    

    public String diskInfo() 
        /* Get a list of all filesystem roots on this system */
        File[] roots = File.listRoots();
        StringBuilder sb = new StringBuilder();

        /* For each filesystem root, print some info */
        for (File root : roots) 
            sb.append("File system root: ");
            sb.append(root.getAbsolutePath());
            sb.append("<br/>");
            sb.append("Total space (bytes): ");
            sb.append(root.getTotalSpace());
            sb.append("<br/>");
            sb.append("Free space (bytes): ");
            sb.append(root.getFreeSpace());
            sb.append("<br/>");
            sb.append("Usable space (bytes): ");
            sb.append(root.getUsableSpace());
            sb.append("<br/>");
        
        return sb.toString();
    

【讨论】:

我的理解是该主题开始询问操作系统中可用的内存量。 freeMemory 这里返回 JVM 中可用的内存量,这是非常不同的 你的类 SystemInfo 不以 Capital 开头,而你的方法 Info(), OSname() , MemInfo() 是不是很奇怪?【参考方案3】:

如果您使用的是 Sun JVM,并且对应用程序的内部内存使用情况(您的应用程序使用的分配内存有多少)感兴趣,我更喜欢打开 JVM 内置的垃圾收集日志记录。您只需将 -verbose:gc 添加到启动命令即可。

来自 Sun 文档:

命令行参数 -verbose:gc 每次打印信息 收藏。注意 -verbose:gc 输出的格式是主题 在 J2SE 平台的版本之间进行更改。例如,这里是 大型服务器应用程序的输出:

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

这里我们看到两个次要的集合和一个主要的集合。号码 箭头前后

325407K->83000K (in the first line)

表示垃圾前后活动对象的组合大小 分别收藏。次要收集后,计数包括 不一定是活的但不能被回收的对象,要么 因为他们直接活着,或者因为他们在或 从终身一代中引用。括号内的数字

(776768K) (in the first line)

是总可用空间,不包括永久空间中的空间 代,即总堆减去幸存者空间之一。 次要收集大约需要四分之一秒。

0.2300771 secs (in the first line)

欲了解更多信息,请参阅:http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

【讨论】:

【参考方案4】:

来自here

    OperatingSystemMXBean operatingSystemMXBean = (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);

【讨论】:

List memoryPools = new ArrayList(ManagementFactory.getMemoryPoolMXBeans());长时间使用HeapMemoryAfterLastGC = 0; for (MemoryPoolMXBean memoryPool : memoryPools) if (memoryPool.getType().equals(MemoryType.HEAP)) MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage(); usedHeapMemoryAfterLastGC += poolCollectionMemoryUsage.getUsed(); 感谢您提供显示 CPU 使用率检索的唯一答案。 做这个和简单做operatingSystemMXBean.getProcessCpuLoad();有什么区别?根据 Oracle 文档,此方法返回“返回 Java 虚拟机进程的“最近 cpu 使用情况”。”然而我发现你的方法和这个方法之间有一个比较大的数字差异。 @Ishnark 在 Java 8 中,OperatingSystemMXBean 似乎没有提供除 getSystemLoadAverage() 之外的任何内容,它“返回最后一分钟的系统负载平均值”。这似乎是在较短的时间内获得估计的唯一方法。 @RobHall 有两个OperatingSystemMXBean 类。一种是java.lang提供的接口。但是还有另一个版本,它在com.sun.management 中扩展了这个版本。这就是我所指的方法来自OperatingSystemMXBean【参考方案5】:

JMX,提供的 MXBean(ThreadMXBean 等)将为您提供内存和 CPU 使用率。

OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();

【讨论】:

【参考方案6】:

对于内存使用,以下将起作用,

long total = Runtime.getRuntime().totalMemory();
long used  = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

对于 CPU 使用率,您需要使用外部应用程序来衡量它。

【讨论】:

【参考方案7】:

从 Java 1.5 开始,JDK 附带了一个新工具:JConsole,它可以显示任何 1.5 或更高版本 JVM 的 CPU 和内存使用情况。它可以绘制这些参数的图表,导出为 CSV,显示加载的类数、实例数、死锁、线程等......

【讨论】:

【参考方案8】:

如果您使用已在此处发布的许多答案(我已经做过很多)的运行时/总内存解决方案,如果您想要相当准确/一致的结果,请务必先强制执行两次垃圾回收。

为了提高效率,Java 通常允许垃圾在强制 GC 之前填满所有内存,即使这样,它通常也不是完整的 GC,因此 runtime.freeMemory() 的结果总是介于“实际”空闲量之间内存和0。

第一个 GC 并没有得到所有东西,它得到了大部分。

好处是,如果你只调用 freeMemory(),你会得到一个绝对无用且变化很大的数字,但如果先做 2 gc,它是一个非常可靠的指标。它还使例程变得更慢(可能是几秒钟)。

【讨论】:

【参考方案9】:

Java 的Runtime 对象可以报告JVM 的内存使用情况。对于 CPU 消耗,您必须使用外部实用程序,例如 Unix 的***或 Windows 进程管理器。

【讨论】:

【参考方案10】:

JConsole 是一种监视正在运行的 Java 应用程序的简单方法,或者您可以使用 Profiler 获取有关应用程序的更多详细信息。我喜欢为此使用NetBeans Profiler。

【讨论】:

【参考方案11】:

这里有一些简单的代码来计算当前的内存使用量(以兆字节为单位):

double currentMemory = ( (double)((double)(Runtime.getRuntime().totalMemory()/1024)/1024))- ((double)((double)(Runtime.getRuntime().freeMemory()/1024)/1024));

【讨论】:

【参考方案12】:

我还会添加以下方法来跟踪 CPU 负载:

import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;

double getCpuLoad() 
    OperatingSystemMXBean osBean =
        (com.sun.management.OperatingSystemMXBean) ManagementFactory.
        getPlatformMXBeans(OperatingSystemMXBean.class);
    return osBean.getProcessCpuLoad();

您可以阅读更多here

【讨论】:

【参考方案13】:

YourKit Java 分析器是一个出色的商业解决方案。您可以在CPU profiling 和memory profiling 上的文档中找到更多信息。

【讨论】:

【参考方案14】:

如果您使用的是 Tomcat,请查看 Psi Probe,它可以让您监控内部和外部内存消耗以及许多其他区域。

【讨论】:

【参考方案15】:

对于Eclipse,你可以使用TPTP(Test and Performance Tools Platform)来分析内存使用等。more information

【讨论】:

【参考方案16】:

我想为现有答案添加注释:

这些方法只跟踪 JVM 内存。实际进程可能会消耗更多内存。

java.nio.ByteBuffer.allocateDirect() 是一个函数/库,很容易被遗漏,并且确实分配了本机内存,这不是 Java 内存管理的一部分。

在 Linux 上,您可以使用类似这样的方法来获取实际消耗的内存:https://linuxhint.com/check_memory_usage_process_linux/

【讨论】:

以上是关于如何检查 Java 中的 CPU 和内存使用情况?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查linux服务器cpu,内存性能

怎么查看电脑CPU和内存使用情况

Prometheus 查询以获取 kubernetes pod 中的 CPU 和内存使用情况

如何使用 WMI 了解进程的 CPU 和内存使用情况?

如何使用JVisualVM远程监控和优化Tomcat和Java程序的内存和CPU

java如何获取系统内存、cpu等信息。