Pregunta

Actualmente estoy creando una aplicación Java que podría terminar ejecutándose en muchas plataformas diferentes, pero principalmente variantes de Solaris, Linux y Windows.

¿Alguien ha podido extraer con éxito información como el espacio en disco actual utilizado, la utilización de la CPU y la memoria utilizada en el sistema operativo subyacente? ¿Qué hay de lo que está consumiendo la aplicación Java?

Preferiblemente me gustaría obtener esta información sin utilizar JNI.

¿Fue útil?

Solución

Puede obtener cierta información de memoria limitada de la clase Runtime. Realmente no es exactamente lo que estás buscando, pero pensé que te lo proporcionaría por completo. Aquí hay un pequeño ejemplo. Editar: También puede obtener información sobre el uso del disco de la clase java.io.File. El uso del espacio en disco requiere Java 1.6 o superior.

public class Main {
  public static void main(String[] args) {
    /* Total number of processors or cores available to the JVM */
    System.out.println("Available processors (cores): " + 
        Runtime.getRuntime().availableProcessors());

    /* Total amount of free memory available to the JVM */
    System.out.println("Free memory (bytes): " + 
        Runtime.getRuntime().freeMemory());

    /* This will return Long.MAX_VALUE if there is no preset limit */
    long maxMemory = Runtime.getRuntime().maxMemory();
    /* Maximum amount of memory the JVM will attempt to use */
    System.out.println("Maximum memory (bytes): " + 
        (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));

    /* Total memory currently available to the JVM */
    System.out.println("Total memory available to JVM (bytes): " + 
        Runtime.getRuntime().totalMemory());

    /* Get a list of all filesystem roots on this system */
    File[] roots = File.listRoots();

    /* For each filesystem root, print some info */
    for (File root : roots) {
      System.out.println("File system root: " + root.getAbsolutePath());
      System.out.println("Total space (bytes): " + root.getTotalSpace());
      System.out.println("Free space (bytes): " + root.getFreeSpace());
      System.out.println("Usable space (bytes): " + root.getUsableSpace());
    }
  }
}

Otros consejos

El java.lang.management el paquete le brinda mucha más información que Runtime; por ejemplo, le proporcionará memoria de pila ( ManagementFactory.getMemoryMXBean (). getHeapMemoryUsage () ) separado de la memoria que no es de pila (< código> ManagementFactory.getMemoryMXBean (). getNonHeapMemoryUsage () ).

También puede obtener el uso de CPU del proceso (sin escribir su propio código JNI), pero debe convertir el java.lang.management.OperatingSystemMXBean en un com.sun.management. OperatingSystemMXBean . Esto funciona en Windows y Linux, no lo he probado en ningún otro lado.

Por ejemplo ... llame al método get getCpuUsage () con más frecuencia para obtener lecturas más precisas.

public class PerformanceMonitor { 
    private int  availableProcessors = getOperatingSystemMXBean().getAvailableProcessors();
    private long lastSystemTime      = 0;
    private long lastProcessCpuTime  = 0;

    public synchronized double getCpuUsage()
    {
        if ( lastSystemTime == 0 )
        {
            baselineCounters();
            return;
        }

        long systemTime     = System.nanoTime();
        long processCpuTime = 0;

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            processCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }

        double cpuUsage = (double) ( processCpuTime - lastProcessCpuTime ) / ( systemTime - lastSystemTime );

        lastSystemTime     = systemTime;
        lastProcessCpuTime = processCpuTime;

        return cpuUsage / availableProcessors;
    }

    private void baselineCounters()
    {
        lastSystemTime = System.nanoTime();

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            lastProcessCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }
    }
}

Creo que el mejor método es implementar la API SIGAR de Hyperic . Funciona para la mayoría de los principales sistemas operativos (casi nada moderno) y es muy fácil trabajar con él. Los desarrolladores son muy receptivos en sus foros y listas de correo. También me gusta que sea GPL2 licencia de Apache . ¡También proporcionan un montón de ejemplos en Java!

SIGAR == Herramienta de información del sistema, recopilación e informes.

Hay un proyecto Java que utiliza JNA (por lo que no es necesario instalar bibliotecas nativas) y está en desarrollo activo. Actualmente es compatible con Linux, OSX, Windows, Solaris y FreeBSD y proporciona información de RAM, CPU, batería y sistema de archivos.

Puede obtener información a nivel del sistema utilizando System.getenv () , pasando el nombre de la variable de entorno relevante como parámetro. Por ejemplo, en Windows:

System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

Para otros sistemas operativos, la presencia / ausencia y los nombres de las variables de entorno relevantes serán diferentes.

Para Windows fui de esta manera.

    com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    long physicalMemorySize = os.getTotalPhysicalMemorySize();
    long freePhysicalMemory = os.getFreePhysicalMemorySize();
    long freeSwapSize = os.getFreeSwapSpaceSize();
    long commitedVirtualMemorySize = os.getCommittedVirtualMemorySize();

Aquí está el link con detalles.

Añadir dependencia OSHI a través de maven:

<dependency>
    <groupId>com.github.dblock</groupId>
    <artifactId>oshi-core</artifactId>
    <version>2.2</version>
</dependency>

Consigue una capacidad de batería restante en porcentaje:

SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
for (PowerSource pSource : hal.getPowerSources()) {
    System.out.println(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
}

Eche un vistazo a las API disponibles en paquete java.lang.management . Por ejemplo:

  • OperatingSystemMXBean.getSystemLoadAverage()
  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()

También hay muchas otras cosas útiles allí.

Por lo general, para obtener información del sistema operativo de bajo nivel, puede invocar comandos específicos del sistema operativo que le brinden la información que desea con Runtime.exec () o leer archivos como / proc / * en Linux.

El uso de la CPU no es sencillo: java.lang.management a través de com.sun.management.OperatingSystemMXBean.getProcessCpuTime se acerca (vea el excelente fragmento de código de Patrick arriba) pero tenga en cuenta que solo da acceso al tiempo que la CPU pasó en su proceso. no le informará sobre el tiempo de CPU empleado en otros procesos, ni siquiera sobre el tiempo de CPU dedicado a las actividades del sistema relacionadas con su proceso.

por ejemplo, tengo un proceso de Java intensivo en red: es lo único que se ejecuta y la CPU está al 99%, pero solo el 55% de eso se informa como "CPU del procesador".

ni siquiera me refiero a " cargar promedio " ya que es casi inútil, a pesar de ser el único elemento relacionado con la CPU en el bean MX. si solo el sol en su sabiduría ocasional expusiera algo como " getTotalCpuTime " ...

para la supervisión seria de la CPU, SIGAR mencionado por Matt parece la mejor opción.

Todavía está en desarrollo, pero ya puede usar jHardware

Es una biblioteca simple que elimina los datos del sistema utilizando Java. Funciona tanto en Linux como en Windows.

ProcessorInfo info = HardwareInfo.getProcessorInfo();
//Get named info
System.out.println("Cache size: " + info.getCacheSize());        
System.out.println("Family: " + info.getFamily());
System.out.println("Speed (Mhz): " + info.getMhz());
//[...]

Si está utilizando Jrockit VM, aquí hay otra forma de obtener el uso de CPU de VM. El bean de tiempo de ejecución también puede proporcionarle una carga de CPU por procesador. He usado esto solo en Red Hat Linux para observar el rendimiento de Tomcat. Debe habilitar el control remoto JMX en catalina.sh para que esto funcione.

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://my.tomcat.host:8080/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);     
MBeanServerConnection conn = jmxc.getMBeanServerConnection();       
ObjectName name = new ObjectName("oracle.jrockit.management:type=Runtime");
Double jvmCpuLoad =(Double)conn.getAttribute(name, "VMGeneratedCPULoad");

En Windows , puede ejecutar el comando systeminfo y recuperar su salida, por ejemplo, con el siguiente código:

private static class WindowsSystemInformation
{
    static String get() throws IOException
    {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("systeminfo");
        BufferedReader systemInformationReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder stringBuilder = new StringBuilder();
        String line;

        while ((line = systemInformationReader.readLine()) != null)
        {
            stringBuilder.append(line);
            stringBuilder.append(System.lineSeparator());
        }

        return stringBuilder.toString().trim();
    }
}

Una forma sencilla que se puede usar para obtener la información a nivel del sistema operativo y que probé en mi Mac que funciona bien:

 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

Puede encontrar muchas métricas relevantes del sistema operativo aquí

Hey, puedes hacer esto con la integración java / com. Al acceder a las funciones de WMI, puede obtener toda la información.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top