Wie überprüfe ich die CPU- und Speichernutzung in Java?

Antworten:

73

Wenn Sie speziell nach Speicher in JVM suchen:

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/>");

Diese sollten jedoch nur als Schätzung herangezogen werden ...

Jeremy
quelle
Wenn ich also in Eclipse ausgeführt werde, hängt dies von meinen Eclipse-Einstellungen ab?
Kaffee
4
Beachten Sie, dass dies nicht der tatsächlich verwendete Speicher ist. Dies ist der 'zugewiesene Speicher', dh der von Java zugewiesene Heap. Wenn Sie also -Xms90g haben und Ihre App sehr leicht ist, erhalten Sie den zugewiesenen Speicher immer noch als etwas größer als 90g . Siehe die Antwort durch gelöschte "unbekannt (yahoo)" unten (was auf den ersten Blick anders sein kann)
0fnt
Nur neugierig, warum sollte dies nur eine Schätzung sein?
ComputerScientist
@ComputerScientist Da kostenlos eigentlich kostenlos ist (nach GC), werden keine Objekte angezeigt, die auf GC warten. Um VIEL genauer zu werden, führen Sie vor dieser Antwort zwei Speicherbereinigungen aus. Wenn Sie es mit und ohne GC versuchen, werden Sie feststellen, dass die Post-GC-Werte sehr konsistent sind, aber der preGC ist im Allgemeinen mindestens doppelt so hoch.
Bill K
@sbeliakov Sie können JavaSysmon ( github.com/jezhumble/javasysmon ) verwenden, obwohl ich Ihnen empfehle, eine neue Frage zu öffnen, und ich werde sie beantworten. Die Bibliothek auf GitHub hat einen Fehler und erkennt 32 Bit als 64 Bit, aber ich habe eine Arbeit gefunden, bei der verschiedene Gläser gemischt werden [ 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();
    }
}
Dave
quelle
Mein Verständnis, dass das Thema begann, war die Frage nach der im Betriebssystem verfügbaren Speichermenge. freeMemoryHier wird die in JVM verfügbare Speichermenge zurückgegeben, die sehr unterschiedlich ist
Tagar
Ist es nicht seltsam, dass Ihre Klasse SystemInfo nicht mit einem Großbuchstaben beginnt und Ihre Methoden Info (), OSname (), MemInfo ()?
Drswaki69
18

Wenn Sie die Sun JVM verwenden und an der internen Speichernutzung der Anwendung interessiert sind (wie viel des zugewiesenen Speichers Ihre App verwendet), schalte ich lieber die integrierte Garbage Collection-Protokollierung der JVMs ein. Sie fügen einfach -verbose: gc zum Startbefehl hinzu.

Aus der Sun-Dokumentation:

Das Befehlszeilenargument -verbose: gc druckt Informationen bei jeder Sammlung. Beachten Sie, dass sich das Format der Ausgabe von -verbose: gc zwischen den Versionen der J2SE-Plattform ändern kann. Hier wird beispielsweise von einer großen Serveranwendung ausgegeben:

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

Hier sehen wir zwei kleinere Sammlungen und eine große. Die Zahlen vor und nach dem Pfeil

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

Geben Sie die kombinierte Größe von lebenden Objekten vor bzw. nach der Speicherbereinigung an. Nach kleineren Sammlungen umfasst die Zählung Objekte, die nicht unbedingt lebendig sind, aber nicht zurückgefordert werden können, entweder weil sie direkt lebendig sind oder weil sie innerhalb der fest angestellten Generation liegen oder von dieser referenziert werden. Die Zahl in Klammern

(776768K) (in the first line)

ist der insgesamt verfügbare Speicherplatz, wobei der Speicherplatz in der permanenten Generation nicht berücksichtigt wird. Dies ist der Gesamthaufen abzüglich eines der Überlebensbereiche. Die kleine Sammlung dauerte ungefähr eine Viertelsekunde.

0.2300771 secs (in the first line)

Weitere Informationen finden Sie unter: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

Steve Blackwell
quelle
17

Von hier aus

    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);
Danieln
quelle
1
Und über die Erinnerung?
Daniel De León
2
List <MemoryPoolMXBean> memoryPools = new ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); long usedHeapMemoryAfterLastGC = 0; für (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). equals (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
Danieln
1
Vielen Dank für die einzige Antwort, die das Abrufen der CPU-Auslastung zeigt.
Matthieu
1
Was ist der Unterschied zwischen dies und einfach zu tun operatingSystemMXBean.getProcessCpuLoad();? Laut Oracle-Dokumentation gibt diese Methode "Gibt die" letzte CPU-Nutzung "für den Java Virtual Machine-Prozess zurück." Ich sehe jedoch einen relativ großen Unterschied zwischen Ihrer Methode und dieser Methode.
Ishnark
1
@RobHall Es gibt zwei OperatingSystemMXBeanKlassen. Eine davon ist die Schnittstelle in java.lang. Es gibt aber auch eine andere Version, die diese erweitert com.sun.management. Das ist die Methode, auf die ich mich bezogOperatingSystemMXBean
Ishnark
9

JMX, Die bereitgestellten MXBeans (ThreadMXBean usw.) geben Ihnen Speicher- und CPU-Auslastung.

OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();
Javamann
quelle
8

Für die Speichernutzung funktioniert Folgendes:

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

Für die CPU-Auslastung müssen Sie eine externe Anwendung verwenden, um sie zu messen.

Rich Adams
quelle
5

Seit Java 1.5 enthält das JDK ein neues Tool: JConsole , das Ihnen die CPU- und Speicherauslastung einer JVM ab 1.5 anzeigt. Es kann Diagramme dieser Parameter erstellen, in CSV exportieren, die Anzahl der geladenen Klassen, die Anzahl der Instanzen, Deadlocks, Threads usw. anzeigen.

Telcontar
quelle
4

Wenn Sie die Runtime / TotalMemory-Lösung verwenden, die hier in vielen Antworten veröffentlicht wurde (das habe ich schon oft getan), müssen Sie zuerst zwei Garbage Collections erzwingen, wenn Sie ziemlich genaue / konsistente Ergebnisse erzielen möchten.

Aus Effizienzgründen lässt Java normalerweise zu, dass Müll den gesamten Speicher ausfüllt, bevor ein GC erzwungen wird, und selbst dann handelt es sich normalerweise nicht um einen vollständigen GC. Daher liegen Ihre Ergebnisse für runtime.freeMemory () immer irgendwo zwischen der "realen" Menge an freiem Speicher und 0 .

Der erste GC bekommt nicht alles, er bekommt das meiste davon.

Der Aufschwung ist, dass Sie, wenn Sie nur den Aufruf von freeMemory () ausführen, eine Nummer erhalten, die absolut nutzlos ist und stark variiert. Wenn Sie jedoch zuerst 2 gc ausführen, ist dies ein sehr zuverlässiges Messgerät. Es macht auch die Routine viel langsamer (Sekunden, möglicherweise).

Bill K.
quelle
3

Das Runtime- Objekt von Java kann die Speichernutzung der JVM melden. Für den CPU-Verbrauch müssen Sie ein externes Dienstprogramm wie Unix Top oder Windows Process Manager verwenden.

Mondschatten
quelle
2

Hier ist ein einfacher Code zur Berechnung der aktuellen Speichernutzung in Megabyte:

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

Ich würde auch den folgenden Weg hinzufügen, um die CPU-Last zu verfolgen:

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

Sie können mehr lesen hier

sbeliakov
quelle
1

JConsole ist eine einfache Möglichkeit, eine laufende Java-Anwendung zu überwachen, oder Sie können einen Profiler verwenden, um detailliertere Informationen zu Ihrer Anwendung zu erhalten. Ich benutze dafür gerne den NetBeans Profiler .

Blahspam
quelle
1

Wenn Sie Tomcat verwenden, lesen Sie Psi Probe , mit dem Sie den internen und externen Speicherverbrauch sowie eine Vielzahl anderer Bereiche überwachen können.

Tim Howland
quelle
0

Für Eclipse können Sie TPTP (Test and Performance Tools Platform) verwenden, um die Speichernutzung usw. zu analysieren. Weitere Informationen

Fuangwith S.
quelle