Come posso monitorare la CPU, la memoria e l’utilizzo del disco in Java?

Vorrei monitorare le seguenti informazioni di sistema in Java:

Sto cercando una soluzione multipiattaforma (Linux, Mac e Windows) che non faccia affidamento sul mio codice che chiama i programmi esterni o che utilizza JNI. Anche se queste sono opzioni valide, preferirei non mantenere il codice specifico del sistema operativo da solo se qualcuno ha già una soluzione migliore.

Se esiste una libreria gratuita che fa questo in modo affidabile e multipiattaforma, sarebbe fantastico (anche se fa chiamate esterne o usa il codice nativo stesso).

Ogni suggerimento è molto apprezzato.

Per chiarire, mi piacerebbe ottenere l’attuale utilizzo della CPU per l’intero sistema, non solo i processi di Java.

L’API SIGAR fornisce tutte le funzionalità che sto cercando in un unico pacchetto, quindi è la migliore risposta alla mia domanda fino ad ora. Tuttavia, a causa della sua licenza sotto licenza GPL, non posso utilizzarlo per il mio scopo originale (una fonte chiusa, prodotto commerciale). È ansible che Hyperic possa concedere in licenza SIGAR per uso commerciale, ma non l’ho esaminato. Per i miei progetti GPL, prenderò sicuramente in considerazione SIGAR in futuro.

Per i miei bisogni attuali, mi sto orientando verso il seguente:

  • Per l’utilizzo della CPU, OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors() (carico medio per CPU)
  • Per memoria, OperatingSystemMXBean.getTotalPhysicalMemorySize() e OperatingSystemMXBean.getFreePhysicalMemorySize()
  • Per spazio su disco, File.getTotalSpace() e File.getUsableSpace()

limitazioni:

I metodi di query getSystemLoadAverage() e spazio su disco sono disponibili solo in Java 6. Inoltre, alcune funzionalità di JMX potrebbero non essere disponibili su tutte le piattaforms (ad esempio, è stato segnalato che getSystemLoadAverage() restituisce -1 su Windows).

Sebbene sia stata originariamente concessa in licenza sotto licenza GPL, è stata modificata in Apache 2.0 , che generalmente può essere utilizzata per prodotti commerciali a sorgente chiusa.

Sulla falsariga di ciò che ho menzionato in questo post . Ti consiglio di utilizzare l’ API SIGAR . Uso l’API SIGAR in una delle mie applicazioni ed è fantastico. Troverete che è stabile, ben supportato e pieno di esempi utili. È open-source con licenza GPL 2 Apache 2.0. Controlla. Ho la sensazione che soddisferà le tue esigenze.

Utilizzando Java e l’API Sigar è ansible ottenere informazioni su memoria, CPU, disco, media del carico, interfaccia di rete e metriche, informazioni sulla tabella di processo, informazioni sulla rotta, ecc.

Il seguente presunto ottiene CPU e RAM. Vedi ManagementFactory per maggiori dettagli.

 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 } 

In JDK 1.7, è ansible ottenere l’utilizzo della CPU e della memoria del sistema tramite com.sun.management.OperatingSystemMXBean . Questo è diverso da 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. 

Dai un’occhiata a questo articolo molto dettagliato: http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime

Per ottenere la percentuale di CPU utilizzata, tutto ciò che serve è una semplice matematica:

 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+"%"); 

Nota: è necessario importare com.sun.management.OperatingSystemMXBean e non java.lang.management.OperatingSystemMXBean .

Funziona perfettamente per me senza alcuna API esterna, solo la funzionalità nascosta Java nativa 🙂

 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()); 

Per lo spazio su disco, se si dispone di Java 6, è ansible utilizzare i metodi getTotalSpace e getFreeSpace su File. Se non sei su Java 6, credo che tu possa usare Apache Commons IO per ottenere un po ‘di là.

Non conosco alcun modo multipiattaforma per avere l’utilizzo della CPU o l’utilizzo della memoria, temo.

Molto di questo è già disponibile tramite JMX. Con Java 5, JMX è integrato e include un visualizzatore di console JMX con JDK.

È ansible utilizzare JMX per monitorare manualmente o invocare comandi JMX da Java se sono necessarie queste informazioni nel proprio run-time.

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

Creare un file batch “Pc.bat” come, typeperf -sc 1 “\ mukit \ processor (_Total) \ %% Processor Time”

Puoi usare la class MProcess,

 / *
  * Md.  Mukit Hasan
  * CSE-JU, 35
  ** /
 import java.io. *; 

MProcessor di class pubblica {

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()); } }

}

Quindi, dopo alcune manipolazioni delle stringhe, si ottiene l’utilizzo della CPU. È ansible utilizzare lo stesso processo per altre attività.

– Mukit Hasan

Il seguente codice è solo Linux (forse Unix), ma funziona in un vero progetto.

  private double getAverageValueByLinux() throws InterruptedException { try { long delay = 50; List listValues = new ArrayList(); for (int i = 0; i < 100; i++) { long cput1 = getCpuT(pattern); Thread.sleep(delay); long cput2 = getCpuT(pattern); 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(Pattern pattern) throws FileNotFoundException, IOException { BufferedReader reader = new BufferedReader(new FileReader("/proc/stat")); String line = reader.readLine(); 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; }