【问题标题】:How do I monitor the computer's CPU, memory, and disk usage in Java?如何在 Java 中监控计算机的 CPU、内存和磁盘使用情况?
【发布时间】:2010-09-08 00:16:51
【问题描述】:

我想用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() 在 Windows 上返回 -1)。

虽然最初是在 GPL 下授权的,但它 has been changedApache 2.0,通常可用于闭源、商业产品。

【问题讨论】:

  • 澄清一下,sigar api 为您获取系统信息。如果你想要 jvm 信息,请使用 JMX。
  • SIGAR 在 GPL 下并不妨碍您使用它,它只是意味着您必须联系作者并请求替代许可。作者通常乐于接受少量费用并允许商业许可。
  • 由于 SIGAR 1.6.4 版本使用的是 Apache 许可证。
  • 您知道如何获取每个处理器的负载吗?

标签: java memory cross-platform cpu diskspace


【解决方案1】:
    OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
    System.out.println((osBean.getCpuLoad() * 100) + "%");

导入com.sun.management.OperatingSystemMXBean

它只在第二次调用后才开始工作,所以保存 osBean 并将其放入循环中

【讨论】:

    【解决方案2】:

    在 JDK 1.7 中,您可以通过com.sun.management.OperatingSystemMXBean 获取系统 CPU 和内存使用情况。这与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.
    

    【讨论】:

    • 这似乎是命中注定。在 FreeBSD 10 和 OpenJDK 8 上获得 -1 的 CPU 负载。
    • 检查这个问题stackoverflow.com/q/19781087/1206998。它说需要几秒钟才能生效。 (注意:我没试过)
    【解决方案3】:

    以下代码仅适用于 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;
    }
    

    【讨论】:

    • 这实际上是我一直在寻找的,但是代码缺少用于从 /proc/stat 中查找 cpu 信息的 REGEX 模式
    • 模式是什么??
    【解决方案4】:

    2008 年接受的答案推荐 SIGAR。然而,正如 2014 年的评论 (@Alvaro) 所说:

    使用 Sigar 时要小心,x64 机器上存在问题... Sigar 1.6.4 is crashing: EXCEPTION_ACCESS_VIOLATION 好像是图书馆 自 2010 年以来没有更新

    我的建议是使用https://github.com/oshi/oshi

    或者answer mentioned above

    【讨论】:

      【解决方案5】:

      按照我提到的in this post。我建议您使用SIGAR API。我在自己的一个应用程序中使用了 SIGAR API,它很棒。你会发现它很稳定,得到很好的支持,并且有很多有用的例子。它是具有 GPL 2 Apache 2.0 许可证的开源软件。看看这个。我感觉它会满足您的需求。

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

      【讨论】:

      【解决方案6】:

      下面的内容可能会为您提供 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
      }
      

      【讨论】:

      • 上述代码的示例输出。此代码确实适用于 Java 1.5。 getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
      • AFAIK getProcessCpuTime = 390625000 只是该线程运行了多长时间。这对于确定处理器使用情况并不是很有用
      • 不确定它是否真的可靠。在具有 4GB 物理内存的 Windows XP 上,它仅报告 2GB(使用 Java 6 和 Java 7 测试)。总交换大小也是错误的。
      • @EmmanuelBourg 只是为看到此主题的人记录,有一个与此相关的 bug
      • 这个方法在 Java 9 之前运行良好,现在由于 Java 正在使用新的访问检查框架,它会抛出 java.lang.reflect.InaccessibleObjectException。
      【解决方案7】:

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

      要获得 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

      【讨论】:

      • 这是一个非常好的答案。所有其他技术都给出了非常奇怪和不可靠的结果,但是这个带有一些尾随平均的技术对我来说就像一个魅力。
      • 当cpu时间高于运行时间(我得到超过100%),是多线程的原因,还是怎么理解?
      • 链接失效了,MBeanServerConnection是什么包?
      【解决方案8】:
      /* 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) { }
              }
          }
      

      【讨论】:

        【解决方案9】:

        这对我来说非常适用,无需任何外部 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,所以我很高兴。
        • 任何线索为什么第二次调用显示 0.0 ?在 OpenJDK v8 上。
        • 别忘了:“import java.lang.management.ManagementFactory;”
        • getProcessCpuLoad 和 getSystemCpuLoad 以我的形式返回 -1。我正在使用 jdk 1.8
        • 没有获取线程数的方法?只是想知道为什么?
        【解决方案10】:

        制作一个批处理文件“Pc.bat”为, typeperf -sc 1 "\mukit\processor(_Total)\%% 处理器时间"

        你可以使用MProcess类,

        /* *医学博士。穆吉特哈桑 *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 使用率。您可以将相同的流程用于其他任务。

        --穆吉特·哈桑

        【讨论】:

        【解决方案11】:

        其中很多已经可以通过 JMX 获得。在 Java 5 中,JMX 是内置的,它们包括一个带有 JDK 的 JMX 控制台查看器。

        如果您在自己的运行时需要此信息,您可以使用 JMX 手动监控,或从 Java 调用 JMX 命令。

        【讨论】:

          【解决方案12】:

          对于磁盘空间,如果您有 Java 6,则可以在 File 上使用 getTotalSpacegetFreeSpace 方法。如果您不在 Java 6 上,我相信您可以使用 Apache Commons IO 来获得一些帮助。

          恐怕我不知道任何跨平台的方法来获取 CPU 使用率或内存使用率。

          【讨论】:

            猜你喜欢
            • 2013-07-07
            • 1970-01-01
            • 2013-05-03
            • 2011-08-04
            • 1970-01-01
            • 2016-02-19
            • 2015-05-23
            • 2021-02-08
            • 1970-01-01
            相关资源
            最近更新 更多