Jak sprawdzić użycie procesora i pamięci w Javie?

Odpowiedzi:

73

Jeśli szukasz konkretnie pamięci w 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/>");

Należy je jednak traktować tylko jako szacunki ...

Jeremy
źródło
Więc jeśli korzystam z Eclipse, będzie to zależeć od moich ustawień Eclipse?
Kawa
4
Zwróć uwagę, że nie jest to rzeczywista używana pamięć - jest to `` przydzielona pamięć '', co oznacza stertę przydzieloną przez Javę, więc jeśli masz -Xms90g, a Twoja aplikacja jest bardzo lekka, nadal zostanie przydzielona pamięć jako coś więcej niż 90g . Zobacz odpowiedź przez usunięte „nieznane (yahoo)” poniżej (które na pierwszy rzut oka może wyglądać inaczej)
0fnt
Ciekawe, dlaczego miałyby to być tylko szacunki?
ComputerScientist
@ComputerScientist Ponieważ free jest w rzeczywistości tym, co jest darmowe (po GC), nie pokazuje obiektów czekających na GC. Aby uzyskać ZNACZNIE dokładniejsze, uruchom 2 operacje czyszczenia pamięci przed tą odpowiedzią. Jeśli spróbujesz tego z GC i bez niego, okaże się, że wartości po GC są bardzo spójne, ale preGC będzie generalnie co najmniej dwukrotnie wyższe.
Bill K
@sbeliakov Możesz skorzystać z JavaSysmon ( github.com/jezhumble/javasysmon ), chociaż polecam otworzyć nowe pytanie, na które odpowiem. Biblioteka na GitHubie ma błąd i rozpoznaje 32-bitowe jako 64-bitowe, ale znalazłem sposób na mieszanie różnych słoików [ 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
źródło
Rozumiem, że temat się zaczął, to pytanie o ilość dostępnej pamięci w systemie operacyjnym. freeMemorytutaj zwraca ilość pamięci dostępnej w JVM, która jest bardzo różna
Tagar
Czy to nie dziwne, że twoja klasa SystemInfo nie zaczyna się od Capital, a twoje metody Info (), OSname (), MemInfo () tak robią?
Drswaki69
18

Jeśli korzystasz z maszyny JVM firmy Sun i interesuje Cię użycie pamięci wewnętrznej aplikacji (ile z przydzielonej pamięci wykorzystuje Twoja aplikacja), wolę włączyć wbudowane rejestrowanie pamięci masowej JVM. Po prostu dodajesz -verbose: gc do polecenia startowego.

Z dokumentacji Sun:

Argument wiersza poleceń -verbose: gc wyświetla informacje w każdej kolekcji. Zwróć uwagę, że format wyjścia -verbose: gc może się zmieniać między wersjami platformy J2SE. Na przykład tutaj jest wyjście z dużej aplikacji serwerowej:

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

Tutaj widzimy dwie mniejsze kolekcje i jedną większą. Liczby przed i za strzałką

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

wskazują łączny rozmiar obiektów na żywo odpowiednio przed i po wyrzucaniu elementów bezużytecznych. Po mniejszych kolekcjach liczba obejmuje obiekty, które niekoniecznie są żywe, ale nie można ich odzyskać, ponieważ są bezpośrednio żywe lub dlatego, że znajdują się w obrębie istniejącej generacji lub istnieją do nich odniesienia. Liczba w nawiasach

(776768K) (in the first line)

jest całkowitą dostępną przestrzenią, nie licząc miejsca w trwałej generacji, która jest całkowitą stertą minus jedno z miejsc ocalałych. Mniejsza kolekcja zajęła około ćwierć sekundy.

0.2300771 secs (in the first line)

Więcej informacji można znaleźć pod adresem: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

Steve Blackwell
źródło
17

od tutaj

    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
źródło
1
A co z pamięcią?
Daniel De León
2
List <MemoryPoolMXBean> memoryPools = new ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); długo używanyHeapMemoryAfterLastGC = 0; for (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). equals (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
danieln
1
Dziękuję za jedyną odpowiedź pokazującą informacje o zużyciu procesora.
Matthieu
1
Jaka jest różnica między robieniem tego a po prostu robieniem operatingSystemMXBean.getProcessCpuLoad();? Zgodnie z dokumentacją Oracle ta metoda zwraca „Zwraca„ ostatnie użycie procesora ”dla procesu wirtualnej maszyny języka Java. Jednak widzę stosunkowo dużą różnicę liczbową między Twoją metodą a tą metodą.
Ishnark
1
@RobHall Istnieją dwie OperatingSystemMXBeanklasy. Jednym z nich jest interfejs udostępniony w programie java.lang. Ale jest też inna wersja, która rozszerza tę wersję com.sun.management. To metoda, o której mówiłem, pochodzi z tegoOperatingSystemMXBean
Ishnark
9

JMX, MXBeans (ThreadMXBean itp.) Zapewnią wykorzystanie pamięci i procesora.

OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();
Javamann
źródło
8

W przypadku użycia pamięci będą działać następujące elementy:

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

Aby zmierzyć zużycie procesora, musisz użyć zewnętrznej aplikacji.

Rich Adams
źródło
6

Od wersji Java 1.5 JDK jest dostarczany z nowym narzędziem: JConsole, które może pokazać użycie procesora i pamięci dowolnej JVM 1.5 lub nowszej. Może tworzyć wykresy tych parametrów, eksportować do CSV, pokazywać liczbę załadowanych klas, liczbę instancji, zakleszczeń, wątków itp.

Telcontar
źródło
4

Jeśli korzystasz z rozwiązania runtime / totalMemory, które zostało opublikowane w wielu odpowiedziach tutaj (zrobiłem to dużo), pamiętaj, aby najpierw wymusić dwa operacje czyszczenia pamięci, jeśli chcesz uzyskać dość dokładne / spójne wyniki.

Ze względu na wydajność Java zwykle pozwala na zapełnienie całej pamięci przez śmieci przed wymuszeniem GC, a nawet wtedy nie jest to zwykle pełna GC, więc wyniki dla runtime.freeMemory () zawsze znajdują się gdzieś pomiędzy "rzeczywistą" ilością wolnej pamięci a 0 .

Pierwsza GC nie dostanie wszystkiego, a większość.

Wynik jest taki, że jeśli po prostu wykonasz wywołanie freeMemory (), otrzymasz numer, który jest absolutnie bezużyteczny i różni się znacznie, ale jeśli najpierw zrobisz 2 gc, jest to bardzo wiarygodny wskaźnik. Powoduje to również DUŻO spowolnienie rutyny (prawdopodobnie sekundy).

Bill K.
źródło
3

Obiekt Java Runtime może raportować wykorzystanie pamięci maszyny JVM. Do zużycia procesora będziesz musiał użyć zewnętrznego narzędzia, takiego jak top Unix lub Windows Process Manager.

księżycowy cień
źródło
2

JConsole to łatwy sposób na monitorowanie działającej aplikacji Java lub skorzystanie z Profiler, aby uzyskać bardziej szczegółowe informacje o aplikacji. Lubię używać do tego programu NetBeans Profiler .

blahspam
źródło
2

Oto prosty kod do obliczenia aktualnego zużycia pamięci w megabajtach:

double currentMemory = ( (double)((double)(Runtime.getRuntime().totalMemory()/1024)/1024))- ((double)((double)(Runtime.getRuntime().freeMemory()/1024)/1024));
Phil
źródło
2

Dodałbym również następujący sposób śledzenia obciążenia procesora:

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

Możesz przeczytać więcej tutaj

sbeliakov
źródło
1

Jeśli używasz Tomcata, wypróbuj Psi Probe , który pozwala monitorować zużycie pamięci wewnętrznej i zewnętrznej, a także wiele innych obszarów.

Tim Howland
źródło
0

W przypadku Eclipse możesz użyć TPTP (Platforma narzędzi testowych i wydajnościowych) do analizy użycia pamięci i innych informacji

Fuangwith S.
źródło