2008-09-06 32 views
137

me gustaría controlar la siguiente información del sistema en Java:¿Cómo controlo la CPU, la memoria y el uso del disco de la computadora en Java?

  • uso de la CPU actual ** (por ciento)
  • disponible de memoria * (libre/total)
  • espacio en disco disponible (libre/total)

    * Tenga en cuenta que me refiero a la memoria general disponible para todo el sistema, no solo la JVM.

Busco una solución multiplataforma (Linux, Mac y Windows) que no se basa en mi propio código llamar programas externos o el uso de JNI. Aunque estas son opciones viables, preferiría no mantener el código específico del sistema operativo si alguien ya tiene una mejor solución.

Si hay una biblioteca gratuita que hace esto de una manera fiable y multiplataforma, sería genial (incluso si realiza llamadas externas o utiliza el código nativo en sí).

Cualquier sugerencia es muy apreciada.

Para aclarar, me gustaría obtener el uso actual de la CPU para todo el sistema, no solo para el (los) proceso (s) Java.

La API de SIGAR proporciona toda la funcionalidad que estoy buscando en un paquete, por lo que es la mejor respuesta a mi pregunta hasta el momento. Sin embargo, debido a que está licenciado bajo la GPL, no puedo usarlo para mi propósito original (un producto comercial de código cerrado). Es posible que Hyperic pueda licenciar SIGAR para uso comercial, pero no lo he investigado. Para mis proyectos GPL, definitivamente consideraré SIGAR en el futuro.

Para mis necesidades actuales, me estoy inclinando hacia el siguiente:

  • Para uso de la CPU, OperatingSystemMXBean.getSystemLoadAverage()/OperatingSystemMXBean.getAvailableProcessors() (promedio de carga por CPU)
  • Para la memoria, y OperatingSystemMXBean.getTotalPhysicalMemorySize()OperatingSystemMXBean.getFreePhysicalMemorySize()
  • Por espacio de disco, File.getTotalSpace() y File.getUsableSpace()

Limitaciones:

El getSystemLoadAverage() y los métodos de consulta de espacio en disco solo están disponibles en Java 6. Además, es posible que algunas funciones JMX no estén disponibles para todas las plataformas (es decir, se informó que getSystemLoadAverage() devuelve -1 en Windows).

Aunque originalmente fue licenciado bajo GPL, es has been changed a Apache 2.0, que generalmente se puede usar para productos comerciales de código cerrado.

+0

Para aclarar, la API sigar le consigue información del sistema. Si desea información jvm, use JMX. –

+0

SIGAR estar bajo la GPL no le impide usarlo, solo significa que debe ponerse en contacto con los autores y solicitar licencias alternativas. Los autores a menudo aceptan con gusto una pequeña tarifa y permiten licencias comerciales. –

+4

Desde la versión 1.6.4 SIGAR está utilizando la licencia de Apache. – Soundlink

Respuesta

59

En la línea de lo que mencioné in this post. Te recomiendo que uses el SIGAR API. Uso la API SIGAR en una de mis propias aplicaciones y es genial. Descubrirá que es estable, bien soportado y lleno de ejemplos útiles. Es de código abierto con una licencia GPL 2 Apache 2.0. Echale un vistazo. Tengo la sensación de que satisfará sus necesidades.

Uso de Java y la API de Sigar puede obtener memoria, CPU, disco, carga-media, la información de interfaz de red y la métrica, la información de la tabla de procesos, información de rutas, etc.

+8

Tenga cuidado al usar Sigar, hay problemas en las máquinas x64 ... http://stackoverflow.com/questions/23405832/sigar-1-6-4-is-useless-exception-access-violation y parece que la biblioteca no se actualiza desde 2010 – Alvaro

8

Para el espacio en disco, si tiene Java 6, puede utilizar los métodos getTotalSpace y getFreeSpace en Archivo. Si no está en Java 6, creo que puede usar Apache Commons IO para obtener parte del camino hasta allí.

No sé de ninguna forma de plataforma cruzada para obtener el uso de la CPU o el uso de la memoria, me temo.

43

Lo siguiente supuestamente le proporciona CPU y RAM. Vea ManagementFactory para más detalles.

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

Muestra de salida para el código anterior. Este código funciona en Java 1.5. getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295 – blak3r

+0

yo sepa getProcessCpuTime = 390625000 sólo es cuánto tiempo que el hilo ha estado funcionando. Eso no es realmente útil para determinar el uso del procesador – MikeNereson

+1

No estoy seguro de que sea realmente confiable. En Windows XP con 4 GB de memoria física, solo informa 2 GB (probado con Java 6 y Java 7). El tamaño total del intercambio también es incorrecto. –

5

Mucho de esto ya está disponible a través JMX. Con Java 5, JMX está integrado e incluye un visor de consola JMX con el JDK.

Puede usar JMX para monitorear manualmente o invocar comandos JMX desde Java si necesita esta información en su propio tiempo de ejecución.

3

El siguiente código es Linux (quizás solo Unix), pero funciona en un proyecto real.

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(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; 
} 
+0

Esto es realmente lo que estaba buscando, pero al código le falta el patrón REGEX para encontrar la información de la CPU de/proc/stat –

+0

¿cuál es el patrón? – HCarrasko

3

hacer un archivo por lotes "Pc.bat", como, typeperf -SC 1 "\ Mukit \ procesador (_Total) \ %% tiempo de procesador"

Puede utilizar la clase MProcess,

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

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

}

Luego, después de un poco de manipulación de cadenas, se obtiene el uso de la CPU. Puede usar el mismo proceso para otras tareas.

--Mukit Hasan

+1

para mí (Win XP) la línea de comando correcta era: 'typeperf" \ processor (_total) \% de tiempo de procesador "' Si lo coloca en un archivo por lotes, use %% en vez de%. Utilicé [technet.microsoft.com/en-us/library/bb490960.aspx](http://technet.microsoft.com/en-us/library/bb490960.aspx). – tutejszy

14

Tener un vistazo a este artículo muy detallado: http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime

Para obtener el porcentaje de CPU utilizado, todo lo que necesita es algo de matemáticas simples:

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: Debe importar com.sun.management.OperatingSystemMXBean y no java.lang.management.OperatingSystemMXBean.

23

En JDK 1.7, puede obtener la CPU del sistema y el uso de memoria a través de com.sun.management.OperatingSystemMXBean. Esto es diferente de 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. 
+0

Estoy usando java1.8. import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; public class Prueba { \t public void (String [] a) { \t \t OperatingSystemMXBean oSMXBean = ManagementFactory.getOperatingSystemMXBean(); \t \t \t} } En el código anterior no puedo encontrar los métodos especificados. He comprobado que el método docs there está disponible para esta clase. Pero no puedo encontrar en el código. Por favor ayuda; – Abdul

+3

Parece que esto es al azar. Obteniendo -1 para la carga de la CPU en FreeBSD 10 y OpenJDK 8. – cen

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) { } 
     } 
    } 
12

Esto funciona perfectamente para mí sin ningún API externa, Java oculta función acaba nativo :)

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

Honesto, creo que esta es la mejor respuesta, funciona en Linux, así que estoy feliz. – ArsenArsen

+1

¿Alguna pista de por qué una segunda invocación muestra 0.0? En OpenJDK v8. – vorburger

+0

No olvide: "import java.lang.management.ManagementFactory;" –

Cuestiones relacionadas