Come posso controllare la CPU e l'utilizzo della memoria in Java?


Risposte:


73

Se stai cercando specificamente la memoria in 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/>");

Tuttavia, questi dovrebbero essere presi solo come una stima ...


Quindi se sto eseguendo in Eclipse, questo dipenderà dalle mie impostazioni di Eclipse?
Caffè

4
Nota che questa non è la memoria effettivamente utilizzata: questa è la 'memoria allocata' che significa l'heap che java ha allocato, quindi se hai -Xms90g e la tua app è molto leggera, ti verrà comunque allocata la memoria come qualcosa di maggiore di 90g . Vedi la risposta cancellata sotto "sconosciuto (yahoo)" (che potrebbe essere diversa a prima vista)
0fnt

Solo curioso, perché dovrebbero essere solo una stima?
ComputerScientist

@ComputerScientist Poiché gratuito è effettivamente ciò che è gratuito (post GC) non mostra oggetti in attesa di GC. Per ottenere MOLTO più accurato, esegui 2 garbage collection prima di questa risposta. Se lo provi con e senza GC, troverai i valori post-GC molto coerenti ma il preGC sarà generalmente almeno il doppio di quelli.
Bill K

@sbeliakov Puoi usare JavaSysmon ( github.com/jezhumble/javasysmon ), anche se ti consiglio di aprire una nuova domanda e risponderò. La libreria su GitHub ha un bug e riconosce 32 bit come 64 bit, ma ho trovato un modo per combinare diversi jar [ 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();
    }
}

a quanto ho capito, l'argomento iniziato chiedeva la quantità di memoria disponibile nel sistema operativo. freeMemoryqui restituisce la quantità di memoria disponibile in JVM che è molto diversa
Tagar

Non è strano che la tua classe SystemInfo non inizi con una maiuscola e i tuoi metodi Info (), OSname (), MemInfo () lo fanno?
Drswaki69,

18

Se stai utilizzando Sun JVM e sei interessato all'utilizzo della memoria interna dell'applicazione (quanta memoria allocata sta utilizzando la tua app), preferisco attivare la registrazione della garbage collection incorporata nella JVM. Devi semplicemente aggiungere -verbose: gc al comando di avvio.

Dalla documentazione Sun:

L'argomento della riga di comando -verbose: gc stampa le informazioni in ogni raccolta. Notare che il formato dell'output -verbose: gc è soggetto a modifiche tra i rilasci della piattaforma J2SE. Ad esempio, ecco l'output di un'applicazione server di grandi dimensioni:

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

Qui vediamo due raccolte minori e una maggiore. I numeri prima e dopo la freccia

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

indicare la dimensione combinata degli oggetti attivi prima e dopo la raccolta dei rifiuti, rispettivamente. Dopo raccolte minori, il conteggio include oggetti che non sono necessariamente vivi ma che non possono essere recuperati, perché sono direttamente vivi o perché appartengono o fanno riferimento alla generazione di ruolo. Il numero tra parentesi

(776768K) (in the first line)

è lo spazio disponibile totale, senza contare lo spazio nella generazione permanente, che è l'heap totale meno uno degli spazi superstiti. La raccolta minore ha richiesto circa un quarto di secondo.

0.2300771 secs (in the first line)

Per maggiori informazioni, vedere: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html


17

Da qui

    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
E sulla memoria?
Daniel De León

2
List <MemoryPoolMXBean> memoryPools = new ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); long usedHeapMemoryAfterLastGC = 0; per (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). equals (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
danieln

1
Grazie per l'unica risposta che mostra il recupero dell'utilizzo della CPU.
Matthieu

1
Qual è la differenza tra fare questo e farlo semplicemente operatingSystemMXBean.getProcessCpuLoad();? Secondo la documentazione Oracle, questo metodo restituisce "Restituisce l '" utilizzo recente della CPU "per il processo Java Virtual Machine." Tuttavia vedo una differenza numerica relativamente grande tra il tuo metodo e questo metodo.
Ishnark

1
@ RobHall Ci sono due OperatingSystemMXBeanclassi. Uno è l'interfaccia fornita in java.lang. Ma c'è anche un'altra versione, che estende questa in com.sun.management. Questo è il metodo a cui mi riferivo è da quelloOperatingSystemMXBean
Ishnark,

9

JMX, MXBeans (ThreadMXBean, ecc.) Forniti ti forniranno memoria e utilizzo della CPU.

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

8

Per l'utilizzo della memoria, funzionerà quanto segue,

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

Per l'utilizzo della CPU, è necessario utilizzare un'applicazione esterna per misurarlo.


6

A partire da Java 1.5, JDK viene fornito con un nuovo strumento: JConsole che può mostrare l'utilizzo della CPU e della memoria di qualsiasi JVM 1.5 o successiva. Può creare grafici di questi parametri, esportare in CSV, mostrare il numero di classi caricate, il numero di istanze, deadlock, thread ecc ...


4

Se utilizzi la soluzione runtime / totalMemory che è stata pubblicata in molte risposte qui (l'ho fatto molte volte), assicurati di forzare prima due raccolte di rifiuti se desideri risultati abbastanza accurati / coerenti.

Per l'efficienza Java di solito consente a spazzatura di riempire tutta la memoria prima di forzare un GC, e anche in questo caso di solito non è un GC completo, quindi i risultati per runtime.freeMemory () sono sempre da qualche parte tra la quantità "reale" di memoria libera e 0 .

Il primo GC non ottiene tutto, ne ottiene la maggior parte.

La ripresa è che se fai solo la chiamata freeMemory () otterrai un numero che è assolutamente inutile e varia ampiamente, ma se fai prima 2 gc è un indicatore molto affidabile. Rende anche la routine MOLTO più lenta (forse secondi).


3

L' oggetto Runtime di Java può segnalare l'utilizzo della memoria della JVM. Per il consumo della CPU dovrai usare un'utilità esterna, come il top di Unix o Windows Process Manager.


2

JConsole è un modo semplice per monitorare un'applicazione Java in esecuzione oppure puoi utilizzare un Profiler per ottenere informazioni più dettagliate sulla tua applicazione. Mi piace usare NetBeans Profiler per questo.


2

Ecco un semplice codice per calcolare l'utilizzo della memoria corrente in megabyte:

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

2

Aggiungerei anche il seguente modo per tenere traccia del carico della 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();
}

Puoi leggere di più qui



1

Se stai usando Tomcat, controlla Psi Probe , che ti consente di monitorare il consumo di memoria interna ed esterna, nonché una miriade di altre aree.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.