如何在Java中监控计算机的CPU、内存和磁盘使用情况?

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

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

    *注意,我指的是整个系统可用的总内存,而不仅仅是JVM

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

如果有一个免费的库能够以可靠的、跨平台的方式做到这一点,那就太好了(即使它进行外部调用或使用本机代码本身)。

任何建议都非常感谢。

为了澄清,我希望获得整个系统的当前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下授权的,但它已经改变了Apache 2.0,通常可用于闭源商业产品。

304783 次浏览

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

我不知道有任何跨平台的方法来获取CPU使用情况或内存使用情况。

下面的步骤应该可以得到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
}

沿着我提到的在这篇文章中。我建议你使用SIGAR API。我在自己的一个应用程序中使用了SIGAR API,它很棒。你会发现它很稳定,有很好的支持,并且有很多有用的例子。它是开源的,有GPL 2 Apache 2.0许可证。来看看。我觉得它能满足你的需求。

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

通过JMX已经可以获得其中的许多功能。在Java 5中,JMX是内置的,并且包含了一个带有JDK的JMX控制台查看器。

您可以使用JMX进行手动监视,如果在自己的运行时需要这些信息,也可以从Java调用JMX命令。

下面的代码只适用于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;
}
创建批处理文件“Pc.bat”,如下: typeperf -sc 1 "\mukit\processor(_Total)\%%处理器时间"

你可以使用类MProcess,

< p > < >之前 /* * Md。Mukit哈桑 * CSE-JU, 35 * * / 进口. io . *; < / p >

公共类MProcessor {

public MProcessor() { 字符串年代; 尝试{ Process ps = Runtime.getRuntime().exec("Pc.bat"); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); while((s = br.readLine()) != null) { System.out.println(年代); } } catch(异常ex) { System.out.println (ex.toString ()); } } < /代码> < / >之前 < p >}

然后在一些字符串操作之后,就得到了CPU使用情况。您可以对其他任务使用相同的流程。

——Mukit哈桑

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

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

在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.
/* 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) { }
}
}

这对我来说是完美的,没有任何外部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());

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

使用Sigar时要小心,x64机器上有问题… Sigar 1.6.4正在崩溃:EXCEPTION_ACCESS_VIOLATION和它似乎图书馆

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

或者上面提到的答案

    OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
System.out.println((osBean.getCpuLoad() * 100) + "%");

进口com.sun.management.OperatingSystemMXBean

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