Narzędzie wiersza polecenia do znajdowania rozmiaru sterty Java i używanej pamięci (Linux)?


171

Czy istnieje narzędzie wiersza polecenia (Linux) do sprawdzania rozmiaru sterty (i używanej pamięci) aplikacji Java?

Próbowałem przez jmap. Ale daje informacje. o obszarach pamięci wewnętrznej, takich jak Eden / PermGen itp., co nie jest dla mnie przydatne.

Szukam czegoś takiego:

  • Maksymalna pamięć: 1 GB
  • Minimalna pamięć: 256 MB
  • Pamięć sterty: 700 MB
  • Używana pamięć: 460 MB

To wszystko. Wiem, że widzę to w JConsole itp., Ale potrzebuję narzędzia wiersza poleceń (nie mogę włączyć JMX itp.)

Czy znasz takie narzędzie / polecenie?

Odpowiedzi:


149

Każdy proces Java ma pidrozszerzenie, które należy najpierw znaleźć za pomocą jpspolecenia.

Gdy już masz pid, możesz go użyć, jstat -gc [insert-pid-here]aby znaleźć statystyki zachowania sterty zebranych śmieci.

  • jstat -gccapacity [insert-pid-here] przedstawi informacje o generowaniu puli pamięci i możliwościach przestrzeni.

  • jstat -gcutil [insert-pid-here]przedstawi wykorzystanie każdej generacji jako procent jej mocy. Przydatne, aby uzyskać szybki wgląd w użycie.

Zobacz dokumentację jstat w witrynie Oracle.


11
Czy istnieje zalecenie, których opcji jstatnależy użyć, aby zweryfikować tylko ogólne użycie pamięci maszyny JVM? Powiedzmy, że uruchamiasz maszynę JVM od Xms=4gi Xmx=4gi chcesz sprawdzić, ile pamięci jest już używane?
basZero

1
„jstat -gcutil <pid> 250 N” był bardzo przydatny do pobierania N próbek w odstępach 250 ms i wyświetlania wyników jako wartości procentowych dla odpowiednich przestrzeni. Dzięki.
Kerem

3
Warto zauważyć, cytat z jstatOracle Java 8 Podręcznik stronie : This command is experimental and unsupported.
patryk.beza

1
awk 'print {$3+$4+$6+$8}'można wydrukować podsumowanie użycia w kolumnach jstat Javy 8
cybersoft

Miałem problem z innymi odpowiedziami, ale podstawowy ps -ef | grep javapokazał mi argumenty vm, które w moim przypadku zawierały wartość -Xmx, która była wszystkim, czego potrzebowałem.
xdhmoore

66

jvmtop to narzędzie wiersza poleceń, które zapewnia podgląd na żywo kilku wskaźników, w tym sterty.

Przykładowe dane wyjściowe trybu przeglądu VM:

 JvmTop 0.3 alpha (expect bugs)  amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

To rzeczywiście świetne narzędzie, rodzaj htop, ale z metrykami z jstat. Dzięki za sugestię @MRalwasser.
oski86

65

To polecenie wyświetla skonfigurowane rozmiary sterty w bajtach.

java -XX:+PrintFlagsFinal -version | grep HeapSize

Działa również na Amazon AMI na EC2.


26
To nie odpowiada na pytanie, które konkretnie pyta, jak sprawdzić użycie sterty w procesie. To polecenie wyświetla wartości domyślne maszyny JVM we wszystkich procesach.
Madbreaks

10
Jednak jest to dla mnie bardzo pomocna odpowiedź, gdy wchodzę na tę stronę za pośrednictwem wyszukiwarki Google, aby dowiedzieć się, jak znaleźć globalny rozmiar sterty.
Johan

@jumping_monkey nie pośrednie, niepoprawne. Jeśli to, co mówisz, jest prawdą, odpowiedź powinna zostać zredagowana lub możesz dodać nową odpowiedź.
Madbreaks

42

Wypróbuj to zadziałało w Ubuntu i RedHat:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

Dla Windowsa:

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

Dla Maca

java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize'

Dane wyjściowe wszystkich tych poleceń przypominają poniższe:

uintx InitialHeapSize                          := 20655360        {product}
uintx MaxHeapSize                              := 331350016       {product}
uintx PermSize                                  = 21757952        {pd product}
uintx MaxPermSize                               = 85983232        {pd product}
intx ThreadStackSize                           = 1024            {pd product}
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

Aby znaleźć rozmiar w MB, podziel wartość przez (1024 * 1024).


Jak znaleźć użycie pamięci oddzielone stosem, wielkością uprawnień, ... określonym procesem java według pid?
Gary Gauh,

3
@GaryGauh To jest domyślny rozmiar sterty. Aby znaleźć zastosowanie uruchomionej aplikacji, powinieneś zrobić to w kodzie lub możesz użyć jconsole. Oto, co wiem, że powinno być też wiele innych sposobów.
padippista

2
Służy jstat -gc <vmid>do uruchamiania aplikacji.
Micha Wiedenmann

27

Bez używania JMX, którego używa większość narzędzi, jedyne, co możesz zrobić, to użyć

jps -lvm

i wywnioskować, że ustawienia będą pochodzić z opcji wiersza poleceń.

Domyślnie nie możesz uzyskać dynamicznych informacji bez JMX, ale możesz napisać własną usługę, aby to zrobić.

BTW: Wolę używać VisualVM zamiast JConsole.


25

Istnieje narzędzie wiersza poleceń z aspektem wizualnym - jvm-mon . Jest to narzędzie do monitorowania maszyny JVM dla wiersza poleceń, które źle znosi:

  • użycie sterty, rozmiar i maks
  • procesy jvm
  • użycie procesora i GC
  • najpopularniejsze wątki

Metryki i wykresy są aktualizowane, gdy narzędzie jest otwarte.

Próba: jvm-mon


1
Wystarczy zauważyć, że jvm-mon działa tylko dla Java8
tmanolatos

1
^ Jest nowa wersja, która teraz obsługuje również Javę 11.
Andrejs

11

Spóźniona impreza, ale bardzo prostym rozwiązaniem jest użycie skryptu jpsstat.sh. Zapewnia prostą aktualną pamięć , maksymalną pamięć i szczegóły użycia procesora .

  • Przejdź do projektu GitHub i pobierz plik jpsstat.sh
  • Kliknij prawym przyciskiem myszy jpsstat.sh i przejdź do zakładki uprawnień i ustaw ją jako wykonywalną
  • Teraz uruchom skrypt za pomocą następującego polecenia ./jpsstat.sh

Oto przykładowe wyjście skryptu -

=====  ======  =======  =======  =====
 PID    Name   CurHeap  MaxHeap  %_CPU
=====  ======  =======  =======  =====
2777   Test3      1.26     1.26    5.8
2582   Test1      2.52     2.52    8.3
2562   Test2      2.52     2.52    6.4

wydaje się, że nie działa po wyjęciu z pudełka na SUSE Linux (wiersz 38: deklaracja: -A: nieprawidłowa opcja)
Chris

wygląda na to, że pojawia się błąd w deklaracji tablicy asocjacyjnej, która wymaga bash> = 4. Innym problemem może być również uruchomienie skryptu jako "sh jpsstat.sh". Jeśli tak, spróbuj uruchomić skrypt jako „./jpsstat.sh”.
amarjeetAnand

9

W moim przypadku musiałem sprawdzić flagi wewnątrz kontenera docker, który nie miał większości podstawowych narzędzi (ps, pstree ...)

Używając jps, otrzymałem PID uruchomionej maszyny JVM (w moim przypadku 1), a następnie jcmd 1 VM.flagsotrzymałem flagi z uruchomionej maszyny JVM.

To zależy od dostępnych poleceń, ale może to komuś pomóc. :)


8

Z Java8 i nowszych możesz użyć poniższego polecenia:

jcmd JAVA_PROCESS_IDGC.heap_info

Możesz odwołać się do sumy, całkowitej i używanej pamięci z wyjścia.

Sample Command And Output: jcmd 9758 GC.heap_info

PSYoungGen  total 1579520K, used 487543K [0x0000000751d80000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1354240K, 36% used [0x0000000751d80000,0x000000076f99dc40,0x00000007a4800000)
  from space 225280K, 0% used [0x00000007b2400000,0x00000007b2400000,0x00000007c0000000)
  to   space 225280K, 0% used [0x00000007a4800000,0x00000007a4800000,0x00000007b2400000)
ParOldGen       total 3610112K, used 0K [0x0000000675800000, 0x0000000751d80000, 0x0000000751d80000)
  object space 3610112K, 0% used [0x0000000675800000,0x0000000675800000,0x0000000751d80000)
Metaspace       used 16292K, capacity 16582K, committed 16896K, reserved 1064960K
  class space    used 1823K, capacity 1936K, committed 2048K, reserved 1048576K

Aby uzyskać więcej informacji na temat polecenia jcmd, odwiedź link: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html


1
Musisz poprawić swój komentarz. GC.heap_info jest dostępny w Javie 9 i nowszych. Nie jest dostępny w Javie 8. Zobacz inny wątek tutaj: stackoverflow.com/questions/41891127/…
Pavel Molchanov

@PavelMolchanov Jestem w stanie użyć polecenia w jdk1.8.0_172. /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/bin/jcmd 98270 GC.heap_info. Proszę, jeśli możesz, dodaj informacje do poleconego wątku, ponieważ nie mam obecnie wystarczającej reputacji, aby dodać tam komentarz.
vaibhav gupta

Czy używasz komputera Mac? Czy używasz Oracle JDK? Nie wiem, jak to może być dostępne w twoim jdk1.8.0_172, Oracle udokumentowało tę funkcję tylko w Javie 9 i nowszych : docs.oracle.com/javase/9/tools/jcmd.htm . Nie ma go w dokumentacji Oracle JDK dla Javy 8. Nie ma o nim wzmianki w odnośniku, który podałeś na dole: docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/…
Pavel Molchanov

Jeszcze jedno pytanie. Sprawdź wersję JDK, w której działa proces 98270 w Twoim przykładzie. jcmd pobiera dostępne polecenia z JVM procesu (w twoim przypadku 98270). Jeśli proces 98270 jest wykonywany z innym JDK (JDK 9 lub nowszy), zobaczysz polecenie GC.heap_info dostępne nawet w samym JCMD, które pochodzi z Javy 8. Dostępne polecenia mogą być różne dla różnych procesów. Aby uzyskać dostępne polecenia, wykonaj: jcmp <PID> help.
Pavel Molchanov

1
FWIW GC.heap_infojest zdecydowanie dostępne również w OpenJDK 8. Może tylko w najnowszych wersjach? Używam tego: 8u191-b12-2ubuntu0.18.04.1
Per Lundberg

7

Każde podejście powinno dać mniej więcej taką samą liczbę. Zawsze dobrze jest przydzielić stertę -X..m -X..xdla wszystkich pokoleń. Możesz wtedy zagwarantować, a także zrobić ps, aby zobaczyć, jakie parametry zostały przekazane, a zatem są używane.

W przypadku rzeczywistego wykorzystania pamięci można z grubsza porównać VIRT (przydzielone i współdzielone) i RES (faktycznie używane) w porównaniu z wartościami jstat:

W przypadku języka Java 8 zobacz jstat, gdzie te wartości faktycznie oznaczają. Zakładając, że uruchamiasz prostą klasę bez mmap lub przetwarzania plików.

$ jstat -gccapacity 32277
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
215040.0 3433472.0  73728.0  512.0  512.0  67072.0   430080.0  6867968.0   392704.0   392704.0      0.0 1083392.0  39680.0      0.0 1048576.0   4864.0   7225     2
$ jstat -gcutil 32277
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  6.25   0.00   7.96  18.21  98.01  95.29   7228   30.859     2    0.173   31.032

Maks . :

     NGCMX + S0C + S1C + EC    + OGCMX   + MCMX    + CCSMX
   3433472 + 512 + 512 + 67072 + 6867968 + 1083392 + 1048576 = 12 GB

(mniej więcej blisko i poniżej pamięci VIRT)

Max (min, używane):

215040 + 512 + 512 + 67072 + 430080  + 39680    +  4864  = ~ 1GB

(z grubsza zbliżone do pamięci RES)

„Nie cytuj mnie w tej sprawie”, ale VIRT mem jest mniej więcej blisko lub więcej niż przydzielona maksymalna ilość pamięci, ale dopóki używana pamięć jest wolna / dostępna w pamięci fizycznej, JVM nie zgłasza wyjątku pamięci. W rzeczywistości maksymalna pamięć nie jest nawet porównywana z pamięcią fizyczną podczas uruchamiania maszyny JVM, nawet przy wyłączonej wymianie w systemie operacyjnym. Lepsze wyjaśnienie tego, jaka pamięć wirtualna naprawdę jest używana przez proces Java, jest omówione tutaj .


4

Najpierw uzyskaj identyfikator procesu, pierwszą liczbę z wymienionego procesu, z jednego z następujących: (lub po prostu użyj ps aux | grep java, jeśli wolisz)

jps -lvm

Następnie użyj tutaj identyfikatora procesu:

jmap -heap $MY_PID 2>/dev/null | sed -ne '/Heap Configuration/,$p';
jmap -permstat $MY_PID

2

Użycie toppolecenia to najprostszy sposób sprawdzenia wykorzystania pamięci programu.RESkolumna pokazuje rzeczywistą pamięć fizyczną zajmowaną przez proces.

W moim przypadku odczytałem plik 10g w Javie i za każdym razem, gdy otrzymałem wyjątek outOfMemory. Stało się tak, gdy wartość w RESkolumnie osiągnęła wartość ustawioną w -Xmxopcji. Następnie poprzez zwiększenie pamięci za pomocą -Xmxopcji wszystko poszło dobrze.


3
top polecenie pokazuje, ile systemu operacyjnego zostało przekazane maszynie JVM. ten facet pyta, jak możemy zobaczyć wykorzystanie miejsca na stosie w JVM. JVM używa 10g nie oznacza, że ​​rzeczywista przestrzeń na sterty jest pełna 10g danych, ponieważ jvm prawie nigdy nie zwraca pamięci z powrotem do systemu operacyjnego ze sterty, dopóki nie zabijesz procesu.
linehrr

2

Jeśli chodzi o rozmiar sterty Java, w systemie Linux można użyć

ps aux | grep java

lub

ps -ef | grep java

i poszukaj -Xms, -Xmx, aby dowiedzieć się o początkowej i maksymalnej określonej wielkości sterty.

Jeśli jednak dla interesującego procesu Java nie ma opcji -Xms lub -Xmx, oznacza to, że proces Java używa domyślnych rozmiarów sterty. Możesz użyć następującego polecenia, aby znaleźć domyślne rozmiary.

java -XX:+PrintFlagsFinal -version | grep HeapSize

lub konkretny plik jvm, na przykład

/path/to/jdk1.8.0_102/bin/java -XX:+PrintFlagsFinal -version | grep HeapSize

i poszukaj InitialHeapSize i MaxHeapSize, które są w bajtach.


1

Jeśli używasz jrockit, wypróbuj narzędzie wiersza poleceń jrcmd. Na przykład:

$ jrcmd 5127 print_memusage
5127:
Total mapped                  1074596KB           (reserved=3728KB)
-              Java heap       786432KB           (reserved=0KB)
-              GC tables        26316KB          
-          Thread stacks        13452KB           (#threads=34)
-          Compiled code         9856KB           (used=9761KB)
-               Internal          840KB          
-                     OS        15036KB          
-                  Other       146632KB          
-        Java class data        75008KB           (malloced=74861KB #103221 in 18709 classes)
- Native memory tracking         1024KB           (malloced=102KB #8)

Aby uzyskać więcej poleceń, takich jak heap_diagnostics, użyj „jrcmd help”, aby je wyświetlić.

https://blogs.oracle.com/jrockit/entry/why_is_my_jvm_process_larger_t


1
jstat -gccapacity javapid  (ex. stat -gccapacity 28745)
jstat -gccapacity javapid gaps frames (ex.  stat -gccapacity 28745 550 10 )

Przykładowe O / P powyższego polecenia

NGCMN    NGCMX     NGC     S0C  
87040.0 1397760.0 1327616.0 107520.0 

NGCMN   Minimum new generation capacity (KB).
NGCMX   Maximum new generation capacity (KB).
NGC Current new generation capacity (KB).

Więcej informacji na ten temat można znaleźć pod adresem http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html


1

Do tej pory nie ma takiego narzędzia do drukowania pamięci sterty w formacie, o który prosiłeś Jedynym i jedynym sposobem drukowania jest napisanie programu java przy pomocy Runtime Class ,

public class TestMemory {

public static void main(String [] args) {

    int MB = 1024*1024;

    //Getting the runtime reference from system
    Runtime runtime = Runtime.getRuntime();

    //Print used memory
    System.out.println("Used Memory:" 
        + (runtime.totalMemory() - runtime.freeMemory()) / MB);

    //Print free memory
    System.out.println("Free Memory:" 
        + runtime.freeMemory() / mb);

    //Print total available memory
    System.out.println("Total Memory:" + runtime.totalMemory() / MB);

    //Print Maximum available memory
    System.out.println("Max Memory:" + runtime.maxMemory() / MB);
}

}

źródło: https://viralpatel.net/blogs/getting-jvm-heap-size-used-memory-total-memory-using-java-runtime/


To jest źle. jmap -heap <pid> podaje te informacje
vsingh

0

Znajdź identyfikator procesu swojego procesu webapp / java od góry. Użyj sterty jmap, aby uzyskać alokację sterty. Przetestowałem to na AWS-Ec2 dla elastycznej łodygi fasoli

Możesz zobaczyć na obrazku poniżej maksymalne sterty 3 GB dla aplikacji

wprowadź opis obrazu tutaj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.