¿Cómo verifico el uso de CPU y memoria en Java?


Respuestas:


73

Si está buscando específicamente memoria en JVM:

Runtime runtime = Runtime.getRuntime();

NumberFormat format = NumberFormat.getInstance();

StringBuilder sb = new StringBuilder();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();

sb.append("free memory: " + format.format(freeMemory / 1024) + "<br/>");
sb.append("allocated memory: " + format.format(allocatedMemory / 1024) + "<br/>");
sb.append("max memory: " + format.format(maxMemory / 1024) + "<br/>");
sb.append("total free memory: " + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024) + "<br/>");

Sin embargo, estos deben tomarse solo como una estimación ...


Entonces, si estoy corriendo en Eclipse, ¿esto dependerá de mi configuración de Eclipse?
Café

4
Tenga en cuenta que esta no es la memoria utilizada real, esta es la 'memoria asignada', lo que significa el montón que Java ha asignado, por lo que si tiene -Xms90g y su aplicación es muy liviana, aún obtendrá la memoria asignada como algo mayor que 90g . Vea la respuesta por "desconocido (yahoo)" eliminado a continuación (que podría ser diferente a primera vista)
0fnt

Solo por curiosidad, ¿por qué deberían ser solo una estimación?
ComputerScientist

@ComputerScientist Debido a que gratis es en realidad lo que es gratis (post GC), no muestra objetos esperando GC. Para ser MUCHO más preciso, ejecute 2 recolecciones de basura antes de esta respuesta. Si lo prueba con y sin GC, encontrará que los valores post-GC son muy consistentes, pero la preGC generalmente será al menos el doble.
Bill K

@sbeliakov Puedes usar JavaSysmon ( github.com/jezhumble/javasysmon ), aunque te recomiendo que abras una nueva pregunta y la responderé. La biblioteca en GitHub tiene un error y reconoce 32 bits como 64 bits, pero encontré una solución para mezclar diferentes jarras [ github.com/goxr3plus/XR3Player/blob/master/resources/libs/… ].
GOXR3PLUS

20
package mkd.Utils;

import java.io.File;
import java.text.NumberFormat;

public class systemInfo {

    private Runtime runtime = Runtime.getRuntime();

    public String Info() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.OsInfo());
        sb.append(this.MemInfo());
        sb.append(this.DiskInfo());
        return sb.toString();
    }

    public String OSname() {
        return System.getProperty("os.name");
    }

    public String OSversion() {
        return System.getProperty("os.version");
    }

    public String OsArch() {
        return System.getProperty("os.arch");
    }

    public long totalMem() {
        return Runtime.getRuntime().totalMemory();
    }

    public long usedMem() {
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    }

    public String MemInfo() {
        NumberFormat format = NumberFormat.getInstance();
        StringBuilder sb = new StringBuilder();
        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        sb.append("Free memory: ");
        sb.append(format.format(freeMemory / 1024));
        sb.append("<br/>");
        sb.append("Allocated memory: ");
        sb.append(format.format(allocatedMemory / 1024));
        sb.append("<br/>");
        sb.append("Max memory: ");
        sb.append(format.format(maxMemory / 1024));
        sb.append("<br/>");
        sb.append("Total free memory: ");
        sb.append(format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024));
        sb.append("<br/>");
        return sb.toString();

    }

    public String OsInfo() {
        StringBuilder sb = new StringBuilder();
        sb.append("OS: ");
        sb.append(this.OSname());
        sb.append("<br/>");
        sb.append("Version: ");
        sb.append(this.OSversion());
        sb.append("<br/>");
        sb.append(": ");
        sb.append(this.OsArch());
        sb.append("<br/>");
        sb.append("Available processors (cores): ");
        sb.append(runtime.availableProcessors());
        sb.append("<br/>");
        return sb.toString();
    }

    public String DiskInfo() {
        /* Get a list of all filesystem roots on this system */
        File[] roots = File.listRoots();
        StringBuilder sb = new StringBuilder();

        /* For each filesystem root, print some info */
        for (File root : roots) {
            sb.append("File system root: ");
            sb.append(root.getAbsolutePath());
            sb.append("<br/>");
            sb.append("Total space (bytes): ");
            sb.append(root.getTotalSpace());
            sb.append("<br/>");
            sb.append("Free space (bytes): ");
            sb.append(root.getFreeSpace());
            sb.append("<br/>");
            sb.append("Usable space (bytes): ");
            sb.append(root.getUsableSpace());
            sb.append("<br/>");
        }
        return sb.toString();
    }
}

Tengo entendido que el tema comenzó preguntando sobre la cantidad de memoria disponible en el sistema operativo. freeMemoryaquí devuelve la cantidad de memoria disponible en JVM que es muy diferente
Tagar

¿No es extraño que su clase SystemInfo no comience con una Capital y sus métodos Info (), OSname (), MemInfo () sí?
Drswaki69

18

Si está utilizando Sun JVM y está interesado en el uso de la memoria interna de la aplicación (cuánto de la memoria asignada está usando su aplicación), prefiero activar el registro de recolección de basura integrado de la JVM. Simplemente agrega -verbose: gc al comando de inicio.

De la documentación de Sun:

El argumento de la línea de comando -verbose: gc imprime información en cada colección. Tenga en cuenta que el formato de la salida -verbose: gc está sujeto a cambios entre las versiones de la plataforma J2SE. Por ejemplo, aquí se obtiene la salida de una aplicación de servidor grande:

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

Aquí vemos dos colecciones menores y una principal. Los números antes y después de la flecha.

325407K->83000K (in the first line)

indican el tamaño combinado de los objetos activos antes y después de la recolección de basura, respectivamente. Después de las colecciones menores, el recuento incluye objetos que no están necesariamente vivos pero que no pueden recuperarse, ya sea porque están vivos directamente o porque están dentro de la generación titular o se hace referencia a ella. El número entre paréntesis

(776768K) (in the first line)

es el espacio total disponible, sin contar el espacio en la generación permanente, que es el montón total menos uno de los espacios supervivientes. La recopilación menor tomó alrededor de un cuarto de segundo.

0.2300771 secs (in the first line)

Para obtener más información, consulte: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html


17

Desde aqui

    OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
    int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
    long prevUpTime = runtimeMXBean.getUptime();
    long prevProcessCpuTime = operatingSystemMXBean.getProcessCpuTime();
    double cpuUsage;
    try
    {
        Thread.sleep(500);
    }
    catch (Exception ignored) { }

    operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    long upTime = runtimeMXBean.getUptime();
    long processCpuTime = operatingSystemMXBean.getProcessCpuTime();
    long elapsedCpu = processCpuTime - prevProcessCpuTime;
    long elapsedTime = upTime - prevUpTime;

    cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * availableProcessors));
    System.out.println("Java CPU: " + cpuUsage);

1
¿Y sobre la memoria?
Daniel De León

2
Lista <MemoryPoolMXBean> memoryPools = new ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); long usedHeapMemoryAfterLastGC = 0; para (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). es igual a (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
danieln

1
Gracias por la única respuesta que muestra la recuperación del uso de la CPU.
Matthieu

1
¿Cuál es la diferencia entre hacer esto y simplemente hacer operatingSystemMXBean.getProcessCpuLoad();? Según la documentación de Oracle, este método devuelve "Devuelve el" uso reciente de la CPU "para el proceso de la máquina virtual Java". Sin embargo, veo una diferencia numérica relativamente grande entre su método y este método.
Ishnark

1
@RobHall Hay dos OperatingSystemMXBeanclases. Uno es la interfaz proporcionada en java.lang. Pero también hay otra versión, que amplía esta en com.sun.management. Ese es el método al que me refería es de esoOperatingSystemMXBean
Ishnark

9

JMX, los MXBeans (ThreadMXBean, etc.) proporcionados le proporcionarán usos de memoria y CPU.

OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();

8

Para el uso de la memoria, funcionará lo siguiente,

long total = Runtime.getRuntime().totalMemory();
long used  = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Para el uso de CPU, necesitará usar una aplicación externa para medirlo.


5

Desde Java 1.5, el JDK viene con una nueva herramienta: JConsole que puede mostrarle el uso de CPU y memoria de cualquier JVM 1.5 o posterior. Puede hacer gráficos de estos parámetros, exportar a CSV, mostrar el número de clases cargadas, el número de instancias, interbloqueos, hilos, etc.


4

Si usa la solución runtime / totalMemory que se ha publicado en muchas respuestas aquí (lo he hecho mucho), asegúrese de forzar dos recolecciones de basura primero si desea resultados bastante precisos / consistentes.

Para mayor eficiencia, Java generalmente permite que la basura llene toda la memoria antes de forzar un GC, e incluso entonces no suele ser un GC completo, por lo que sus resultados para runtime.freeMemory () siempre estarán en algún lugar entre la cantidad "real" de memoria libre y 0 .

El primer GC no obtiene todo, obtiene la mayor parte.

La ventaja es que si solo haces la llamada freeMemory () obtendrás un número que es absolutamente inútil y varía ampliamente, pero si haces 2 gc's primero, es un indicador muy confiable. También hace que la rutina sea MUCHO más lenta (segundos, posiblemente).


3

El objeto Runtime de Java puede informar sobre el uso de memoria de la JVM. Para el consumo de CPU, tendrá que usar una utilidad externa, como la parte superior de Unix o el Administrador de procesos de Windows.


2

Aquí hay un código simple para calcular el uso de memoria actual en megabytes:

double currentMemory = ( (double)((double)(Runtime.getRuntime().totalMemory()/1024)/1024))- ((double)((double)(Runtime.getRuntime().freeMemory()/1024)/1024));

2

También agregaría la siguiente forma de rastrear la carga de la CPU:

import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;

double getCpuLoad() {
    OperatingSystemMXBean osBean =
        (com.sun.management.OperatingSystemMXBean) ManagementFactory.
        getPlatformMXBeans(OperatingSystemMXBean.class);
    return osBean.getProcessCpuLoad();
}

Puedes leer más aquí


1

JConsole es una manera fácil de monitorear una aplicación Java en ejecución o puede usar un Profiler para obtener información más detallada sobre su aplicación. Me gusta usar NetBeans Profiler para esto.



1

Si está utilizando Tomcat, consulte Psi Probe , que le permite monitorear el consumo de memoria interna y externa, así como una serie de otras áreas.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.