我想在 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 changed 到 Apache 2.0,通常可用于封闭源代码的商业产品。
按照我提到的in this post。我建议您使用 SIGAR API。我在自己的一个应用程序中使用了 SIGAR API,它很棒。你会发现它很稳定,得到很好的支持,并且有很多有用的例子。它是具有 GPL 2 Apache 2.0 许可证的开源软件。一探究竟。我感觉它会满足你的需求。
使用 Java 和 Sigar API,您可以获得内存、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
}
在 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.
这对我来说完美无缺,无需任何外部 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());
要获得使用的 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
。
2008 年接受的答案推荐 SIGAR。然而,正如 2014 年的评论(@Alvaro)所说:
使用 Sigar 时要小心,x64 机器上存在问题... Sigar 1.6.4 正在崩溃:EXCEPTION_ACCESS_VIOLATION 似乎该库自 2010 年以来没有更新
我的建议是使用 https://github.com/oshi/oshi
对于磁盘空间,如果您有 Java 6,则可以对 File 使用 getTotalSpace 和 getFreeSpace 方法。如果您不在 Java 6 上,我相信您可以使用 Apache Commons IO 来获得一些方法。
恐怕我不知道有任何跨平台方式来获取 CPU 使用率或内存使用率。
其中很多已经可以通过 JMX 获得。在 Java 5 中,JMX 是内置的,它们包括一个带有 JDK 的 JMX 控制台查看器。
如果您在自己的运行时需要此信息,您可以使用 JMX 手动监控,或者从 Java 调用 JMX 命令。
/* 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) { }
}
}
以下代码仅适用于 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)\%% Processor Time"
您可以使用 MProcess 类,
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 使用率。您可以将相同的过程用于其他任务。
——穆基特·哈桑
typeperf "\processor(_total)\% processor time"
如果你把它放到批处理文件中,使用 %% 而不是 %。我使用了 technet.microsoft.com/en-us/library/bb490960.aspx。
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
System.out.println((osBean.getCpuLoad() * 100) + "%");
导入com.sun.management.OperatingSystemMXBean
它仅在第二次调用后才开始工作,因此请保存 osBean 并将其置于循环中