如何使用Java监视计算机的CPU,内存和磁盘使用情况?


180

我想用Java监视以下系统信息:

  • 当前的CPU使用率**(百分比)
  • 可用内存*(空闲/总)
  • 可用磁盘空间(可用/总)

    *请注意,我的意思是整个系统可用的整体内存,而不仅仅是JVM。

我正在寻找一种不依赖于我自己的调用外部程序或使用JNI的代码的跨平台解决方案(Linux,Mac和Windows)。尽管这些是可行的选择,但如果有人已经有了更好的解决方案,我宁愿自己不要维护特定于操作系统的代码。

如果有一个免费的库以可靠的跨平台方式执行此操作,那将很棒(即使它进行外部调用或本身使用本机代码)也是如此。

任何建议,不胜感激。

为了澄清,我想获得整个系统的当前CPU使用率,而不仅仅是Java进程。

SIGAR API在一个软件包中提供了我正在寻找的所有功能,因此,这是迄今为止我所提问题的最佳答案。但是,由于它是根据GPL许可的,因此我不能将其用于原始用途(封闭源商业产品)。Hyperic可能会将SIGAR许可用于商业用途,但我尚未对此进行调查。对于我的GPL项目,将来一定会考虑使用SIGAR。

对于我当前的需求,我倾向于以下方面:

  • 对于CPU使用率,OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(每CPU平均负载)
  • 为了记忆,OperatingSystemMXBean.getTotalPhysicalMemorySize()以及OperatingSystemMXBean.getFreePhysicalMemorySize()
  • 对于磁盘空间,File.getTotalSpace()以及File.getUsableSpace()

局限性:

getSystemLoadAverage()和磁盘空间查询方法仅可用的Java 6此外,根据一些JMX功能可能无法适用于所有平台(即它的报道,getSystemLoadAverage()返回-1在Windows上)。

尽管最初是根据GPL许可的,但已将其更改Apache 2.0,通常可用于封闭源商业产品。


澄清一下,sigar api会为您获取系统信息。如果要获取jvm信息,请使用JMX。
马特·卡明斯'09

GGAR下的SIGAR并不阻止您使用它,仅表示您必须联系作者并请求替代许可。作者通常乐于接受一小笔费用并允许商业许可。
亚历克·托马斯

7
从1.6.4版开始,SIGAR使用的是Apache许可证。
2011年

您知道如何获取每个处理器的负载吗?
zcaudate 2012年

Answers:


67

遵循我在这篇文章中提到的内容。我建议您使用SIGAR API。我在自己的一个应用程序中使用了SIGAR API,这很棒。您会发现它是稳定的,受良好支持的,并且充满了有用的示例。它是开源的,具有GPL 2 Apache 2.0许可证。看看这个。我感觉它将满足您的需求。

使用Java和Sigar API,您可以获得内存,CPU,磁盘,平均负载,网络接口信息和度量标准,进程表信息,路由信息等。


14
使用Sigar时要小心,x64机器上有问题... stackoverflow.com/questions/23405832 / ... ,看来该库自2010
Alvaro

56

以下内容可以使您获得CPU和RAM。有关更多详细信息,请参见ManagementFactory

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

private static void printUsage() {
  OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
  for (Method method : operatingSystemMXBean.getClass().getDeclaredMethods()) {
    method.setAccessible(true);
    if (method.getName().startsWith("get")
        && Modifier.isPublic(method.getModifiers())) {
            Object value;
        try {
            value = method.invoke(operatingSystemMXBean);
        } catch (Exception e) {
            value = e;
        } // try
        System.out.println(method.getName() + " = " + value);
    } // if
  } // for
}

3
上面代码的示例输出。此代码在Java 1.5上有效。getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
blak3r

AFAIK getProcessCpuTime = 390625000仅是该线程运行了多长时间。这对于确定处理器使用率并不是真正有用
MikeNereson

2
不确定它是否确实可靠。在具有4GB物理内存的Windows XP上,它仅报告2GB(使用Java 6和Java 7测试)。总交换大小也是错误的。
伊曼纽尔·布尔格

4
@EmmanuelBourg仅是为那些看到此主题的人们提供文档,其中有一个与此相关的错误
塞尔吉奥米歇尔斯

2
在Java 9之前,此方法一直有效,由于Java正在使用新的访问检查框架,因此该方法现在抛出java.lang.reflect.InaccessibleObjectException。
雷·兰开斯特

40

在JDK 1.7中,您可以通过获得系统CPU和内存使用率com.sun.management.OperatingSystemMXBean。这与有所不同java.lang.management.OperatingSystemMXBean

long    getCommittedVirtualMemorySize()
Returns the amount of virtual memory that is guaranteed to be available to the running process in bytes, or -1 if this operation is not supported.

long    getFreePhysicalMemorySize()
Returns the amount of free physical memory in bytes.

long    getFreeSwapSpaceSize()
Returns the amount of free swap space in bytes.

double  getProcessCpuLoad()
Returns the "recent cpu usage" for the Java Virtual Machine process.

long    getProcessCpuTime()
Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds.

double  getSystemCpuLoad()
Returns the "recent cpu usage" for the whole system.

long    getTotalPhysicalMemorySize()
Returns the total amount of physical memory in bytes.

long    getTotalSwapSpaceSize()
Returns the total amount of swap space in bytes.

5
好像是命中注定。在FreeBSD 10和OpenJDK 8上获得-1的CPU负载。–
cen

检查此问题stackoverflow.com/q/19781087/1206998。它说要花几秒钟才能生效。(注意:我没有尝试)
Juh_

25

这对我来说非常完美,不需要任何外部API,只有本机Java隐藏功能:)

import com.sun.management.OperatingSystemMXBean;
...
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
                OperatingSystemMXBean.class);
// What % CPU load this current JVM is taking, from 0.0-1.0
System.out.println(osBean.getProcessCpuLoad());

// What % load the overall system is at, from 0.0-1.0
System.out.println(osBean.getSystemCpuLoad());

老实说,我发现这是最好的答案,可以在Linux上运行,所以我很高兴。
ArsenArsen

1
任何提示为什么第二次调用显示0.0?在OpenJDK v8上。
vorburger

不要忘记:“ import java.lang.management.ManagementFactory;”
伯恩德

1
getProcessCpuLoad和getSystemCpuLoad从我这里返回-1。即时通讯使用jdk 1.8
BurakAkyıldız18年

它没有获取线程计数的方法?只想知道为什么?
djangofan

16

看一下这篇非常详细的文章:http : //nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclassgetJVMCPUtime

要获得使用的CPU百分比,您需要做的是一些简单的数学运算:

MBeanServerConnection mbsc = ManagementFactory.getPlatformMBeanServer();

OperatingSystemMXBean osMBean = ManagementFactory.newPlatformMXBeanProxy(
mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);

long nanoBefore = System.nanoTime();
long cpuBefore = osMBean.getProcessCpuTime();

// Call an expensive task, or sleep if you are monitoring a remote process

long cpuAfter = osMBean.getProcessCpuTime();
long nanoAfter = System.nanoTime();

long percent;
if (nanoAfter > nanoBefore)
 percent = ((cpuAfter-cpuBefore)*100L)/
   (nanoAfter-nanoBefore);
else percent = 0;

System.out.println("Cpu usage: "+percent+"%");

注意:您必须导入com.sun.management.OperatingSystemMXBean而不是java.lang.management.OperatingSystemMXBean


这是一个很好的答案。所有其他技术都给出了非常奇怪和不可靠的结果,但是对我来说,这种具有一些尾随平均的技术就像是一种魅力。
Fractaly

当cpu时间高于经过时间(我超过100%)时,是因为多线程还是如何理解它?
Lukas Hanacek


6

许多这些已经可以通过JMX获得。在Java 5中,JMX是内置的,它们包括JDK的JMX控制台查看器。

您可以使用JMX进行手动监视,或者如果需要在自己的运行时中从Java调用JMX命令。



4
/* YOU CAN TRY THIS TOO */

import java.io.File;
 import java.lang.management.ManagementFactory;
// import java.lang.management.OperatingSystemMXBean;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.management.RuntimeMXBean;
 import java.io.*;
 import java.net.*;
 import java.util.*;
 import java.io.LineNumberReader;
 import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.util.Random;



 public class Pragati
 {

     public static void printUsage(Runtime runtime)
     {
     long total, free, used;
     int mb = 1024*1024;

     total = runtime.totalMemory();
     free = runtime.freeMemory();
     used = total - free;
     System.out.println("\nTotal Memory: " + total / mb + "MB");
     System.out.println(" Memory Used: " + used / mb + "MB");
     System.out.println(" Memory Free: " + free / mb + "MB");
     System.out.println("Percent Used: " + ((double)used/(double)total)*100 + "%");
     System.out.println("Percent Free: " + ((double)free/(double)total)*100 + "%");
    }
    public static void log(Object message)
         {
            System.out.println(message);
         }

        public static int calcCPU(long cpuStartTime, long elapsedStartTime, int cpuCount)
        {
             long end = System.nanoTime();
             long totalAvailCPUTime = cpuCount * (end-elapsedStartTime);
             long totalUsedCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()-cpuStartTime;
             //log("Total CPU Time:" + totalUsedCPUTime + " ns.");
             //log("Total Avail CPU Time:" + totalAvailCPUTime + " ns.");
             float per = ((float)totalUsedCPUTime*100)/(float)totalAvailCPUTime;
             log( per);
             return (int)per;
        }

        static boolean isPrime(int n)
        {
     // 2 is the smallest prime
            if (n <= 2)
            {
                return n == 2;
            }
     // even numbers other than 2 are not prime
            if (n % 2 == 0)
            {
                return false;
            }
     // check odd divisors from 3
     // to the square root of n
         for (int i = 3, end = (int)Math.sqrt(n); i <= end; i += 2)
         {
            if (n % i == 0)
         {
         return false;
        }
        }
 return true;
}
    public static void main(String [] args)
    {
            int mb = 1024*1024;
            int gb = 1024*1024*1024;
             /* PHYSICAL MEMORY USAGE */
             System.out.println("\n**** Sizes in Mega Bytes ****\n");
            com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
            //RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            //operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
            com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)
            java.lang.management.ManagementFactory.getOperatingSystemMXBean();
            long physicalMemorySize = os.getTotalPhysicalMemorySize();
            System.out.println("PHYSICAL MEMORY DETAILS \n");
            System.out.println("total physical memory : " + physicalMemorySize / mb + "MB ");
            long physicalfreeMemorySize = os.getFreePhysicalMemorySize();
            System.out.println("total free physical memory : " + physicalfreeMemorySize / mb + "MB");
            /* DISC SPACE DETAILS */
            File diskPartition = new File("C:");
            File diskPartition1 = new File("D:");
            File diskPartition2 = new File("E:");
            long totalCapacity = diskPartition.getTotalSpace() / gb;
            long totalCapacity1 = diskPartition1.getTotalSpace() / gb;
            double freePartitionSpace = diskPartition.getFreeSpace() / gb;
            double freePartitionSpace1 = diskPartition1.getFreeSpace() / gb;
            double freePartitionSpace2 = diskPartition2.getFreeSpace() / gb;
            double usablePatitionSpace = diskPartition.getUsableSpace() / gb;
            System.out.println("\n**** Sizes in Giga Bytes ****\n");
            System.out.println("DISC SPACE DETAILS \n");
            //System.out.println("Total C partition size : " + totalCapacity + "GB");
            //System.out.println("Usable Space : " + usablePatitionSpace + "GB");
            System.out.println("Free Space in drive C: : " + freePartitionSpace + "GB");
            System.out.println("Free Space in drive D:  : " + freePartitionSpace1 + "GB");
            System.out.println("Free Space in drive E: " + freePartitionSpace2 + "GB");
            if(freePartitionSpace <= totalCapacity%10 || freePartitionSpace1 <= totalCapacity1%10)
            {
                System.out.println(" !!!alert!!!!");
            }
            else
                System.out.println("no alert");

            Runtime runtime;
            byte[] bytes;
            System.out.println("\n \n**MEMORY DETAILS  ** \n");
            // Print initial memory usage.
            runtime = Runtime.getRuntime();
            printUsage(runtime);

            // Allocate a 1 Megabyte and print memory usage
            bytes = new byte[1024*1024];
            printUsage(runtime);

            bytes = null;
            // Invoke garbage collector to reclaim the allocated memory.
            runtime.gc();

            // Wait 5 seconds to give garbage collector a chance to run
            try {
            Thread.sleep(5000);
            } catch(InterruptedException e) {
            e.printStackTrace();
            return;
            }

            // Total memory will probably be the same as the second printUsage call,
            // but the free memory should be about 1 Megabyte larger if garbage
            // collection kicked in.
            printUsage(runtime);
            for(int i = 0; i < 30; i++)
                     {
                         long start = System.nanoTime();
                        // log(start);
                        //number of available processors;
                         int cpuCount = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
                         Random random = new Random(start);
                         int seed = Math.abs(random.nextInt());
                         log("\n \n CPU USAGE DETAILS \n\n");
                         log("Starting Test with " + cpuCount + " CPUs and random number:" + seed);
                         int primes = 10000;
                         //
                         long startCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();
                         start = System.nanoTime();
                         while(primes != 0)
                         {
                            if(isPrime(seed))
                            {
                                primes--;
                            }
                            seed++;

                        }
                         float cpuPercent = calcCPU(startCPUTime, start, cpuCount);
                         log("CPU USAGE : " + cpuPercent + " % ");


                         try
                         {
                             Thread.sleep(1000);
                         }
                         catch (InterruptedException e) {}
        }

            try
            {
                Thread.sleep(500);
            }`enter code here`
            catch (Exception ignored) { }
        }
    }

4

以下代码仅适用于Linux(也许是Unix),但可在实际项目中使用。

    private double getAverageValueByLinux() throws InterruptedException {
    try {

        long delay = 50;
        List<Double> listValues = new ArrayList<Double>();
        for (int i = 0; i < 100; i++) {
            long cput1 = getCpuT();
            Thread.sleep(delay);
            long cput2 = getCpuT();
            double cpuproc = (1000d * (cput2 - cput1)) / (double) delay;
            listValues.add(cpuproc);
        }
        listValues.remove(0);
        listValues.remove(listValues.size() - 1);
        double sum = 0.0;
        for (Double double1 : listValues) {
            sum += double1;
        }
        return sum / listValues.size();
    } catch (Exception e) {
        e.printStackTrace();
        return 0;
    }

}

private long getCpuT throws FileNotFoundException, IOException {
    BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
    String line = reader.readLine();
    Pattern pattern = Pattern.compile("\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)")
    Matcher m = pattern.matcher(line);

    long cpuUser = 0;
    long cpuSystem = 0;
    if (m.find()) {
        cpuUser = Long.parseLong(m.group(1));
        cpuSystem = Long.parseLong(m.group(3));
    }
    return cpuUser + cpuSystem;
}

1
这实际上是我想要的,但是代码缺少用于从/ proc / stat查找cpu信息的REGEX模式
Donal Tobin 2012年

模式是什么??
HCarrasko 2015年

3

制作一个批处理文件“ Pc.bat”,类型为perf -sc 1“ \ mukit \ processor(_Total)\ %% Processor Time”

您可以使用MProcess类,

/ *
 *医学博士 Mukit Hasan
 * CSE-JU,35
 ** / 导入java io 。*;

公共MProcessor {

public MProcessor() { String s; try { Process ps = Runtime.getRuntime().exec("Pc.bat"); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); while((s = br.readLine()) != null) { System.out.println(s); } } catch( Exception ex ) { System.out.println(ex.toString()); } }

}

然后,在进行了一些字符串操作之后,即可使用CPU。您可以对其他任务使用相同的过程。

-穆奇特·哈桑


1
对我来说(Win XP)正确的命令行是:typeperf "\processor(_total)\% processor time"如果将其放在批处理文件中,请使用%%而不是%。我使用了technet.microsoft.com/en-us/library/bb490960.aspx
tutejszy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.