Come posso controllare l'utilizzo della CPU e della memoria in Java?
Ho bisogno di controllare l'utilizzo della CPU e della memoria per il server in java, qualcuno sa come potrebbe essere fatto?
15 answers
Se stai cercando specificamente nella memoria 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 una stima...
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();
}
}
Se si utilizza la JVM Sun e si è interessati all'utilizzo della memoria interna dell'applicazione (quanto della memoria allocata viene utilizzata dall'app), preferisco attivare la registrazione della garbage collection integrata nelle JVM. È sufficiente aggiungere-verbose: gc al comando di avvio.
Dalla documentazione Sun:
L'argomento della riga di comando-verbose: gc stampa le informazioni ad ogni raccolta. Si noti che il formato dell'output-verbose:gc è soggetto per cambiare tra versioni della piattaforma J2SE. Ad esempio, ecco output da 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 collezioni minori e una maggiore. Numero prima e dopo la freccia
325407K->83000K (in the first line)
Indica la dimensione combinata degli oggetti vivi prima e dopo la spazzatura collezione, rispettivamente. Dopo le raccolte minori il conteggio include oggetti che non sono necessariamente vivi ma non possono essere recuperati perché sono direttamente vivi, o perché lo sono entro o riferimento dalla generazione di ruolo. Il numero tra parentesi
(776768K) (in the first line)
È lo spazio disponibile totale, senza contare lo spazio nel permanente generazione, che è l'heap totale meno uno degli spazi sopravvissuti. La collezione 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
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);
JMX, gli MXBeans (ThreadMXBean, ecc.) forniti ti forniranno memoria e usi della CPU.
OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();
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.
Da Java 1.5 il 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ò fare grafici di questi parametri, esportare in CSV, mostrare il numero di classi caricate, il numero di istanze, deadlock, thread ecc...
Se si utilizza la soluzione runtime/totalMemory che è stata pubblicata in molte risposte qui (l'ho fatto molto), assicurarsi di forzare prima due garbage collection se si desidera risultati abbastanza accurati/coerenti.
Per effiency Java di solito consente a garbage di riempire tutta la memoria prima di forzare un GC, e anche allora di solito non è un GC completo, quindi i risultati per il runtime.freeMemory () è sempre da qualche parte tra la quantità "reale" di memoria libera e 0.
Il primo GC non prendi tutto, ottiene la maggior parte di esso.
La ripresa è che se fai semplicemente la chiamata freeMemory() otterrai un numero che è assolutamente inutile e varia ampiamente, ma se fai 2 gc per primo è un indicatore molto affidabile. Rende anche la routine MOLTO più lenta (secondi, possibilmente).
L'oggetto Runtime di Java può segnalare l'utilizzo della memoria della JVM. Per il consumo di CPU dovrai utilizzare un'utilità esterna, come Unix top o Windows Process Manager.
Ecco un semplice codice per calcolare l'utilizzo corrente della memoria in megabyte:
double currentMemory = ( (double)((double)(Runtime.getRuntime().totalMemory()/1024)/1024))- ((double)((double)(Runtime.getRuntime().freeMemory()/1024)/1024));
Vorrei anche aggiungere 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
JConsole è un modo semplice per monitorare un'applicazione Java in esecuzione oppure è possibile utilizzare un Profiler per ottenere informazioni più dettagliate sull'applicazione. Mi piace usare il NetBeans Profiler per questo.
Il profiler Java YourKit è un'ottima soluzione commerciale. È possibile trovare ulteriori informazioni nei documenti su CPU profiling e memory profiling .
Se si utilizza Tomcat, controllare Psi Probe, che consente di monitorare il consumo di memoria interna ed esterna, nonché una serie di altre aree.
Per Eclipse, è possibile utilizzare TPTP (Test and Performance Tools Platform) per analizzare l'utilizzo della memoria e così via. maggiori informazioni