Befehlszeilentool zum Ermitteln der Größe und des verwendeten Java-Heapspeichers (Linux)?

171

Gibt es ein Befehlszeilentool (Linux) zum Überprüfen der Heap-Größe (und des verwendeten Speichers) einer Java-Anwendung?

Ich habe es mit jmap versucht. Aber es gibt Infos. über interne Speicherbereiche wie Eden / PermGen usw., was für mich nicht nützlich ist.

Ich suche so etwas wie:

  • Maximaler Speicher: 1 GB
  • Minimaler Speicher: 256 MB
  • Heap-Speicher: 700 MB
  • Verwendeter Speicher: 460 MB

Das ist alles. Ich weiß, dass ich dies in JConsole usw. sehen kann, aber ich benötige ein Befehlszeilentool (kann JMX usw. nicht aktivieren).

Kennen Sie ein solches Werkzeug / einen solchen Befehl?

Jaspis
quelle

Antworten:

149

Jeder Java-Prozess hat eine pid, die Sie zuerst mit dem jpsBefehl finden müssen.

Sobald Sie die PID haben, können jstat -gc [insert-pid-here]Sie Statistiken über das Verhalten des gesammelten Müllhaufens finden.

  • jstat -gccapacity [insert-pid-here] präsentiert Informationen zur Speicherpoolgenerierung und zu Speicherplatzfunktionen.

  • jstat -gcutil [insert-pid-here]wird die Auslastung jeder Generation als Prozentsatz ihrer Kapazität darstellen. Nützlich, um einen Überblick über die Nutzung zu erhalten.

Siehe jstat-Dokumente auf der Oracle-Website.

Bauer1992
quelle
11
Gibt es eine Empfehlung, welche Optionen verwendet werden jstatsollten, um nur die Gesamtspeicherauslastung einer JVM zu überprüfen? Angenommen, Sie starten die JVM mit Xms=4gund Xmx=4gmöchten sehen, wie viel Speicher davon bereits verwendet wird.
BasZero
1
"jstat -gcutil <pid> 250 N" war sehr nützlich, um N Proben mit Intervallen von 250 ms zu entnehmen und die Ausgabe als Prozentsätze für die entsprechenden Räume anzuzeigen. Vielen Dank.
Kerem
3
Bemerkenswert Zitat von jstatOracle Java 8 Handbuch Seite : This command is experimental and unsupported.
patryk.beza
1
awk 'print {$3+$4+$6+$8}'kann eine zusammengefasste Verwendung in den jstat-Spalten von Java 8 drucken
cybersoft
Hatte Probleme mit den anderen Antworten, aber ein Basic ps -ef | grep javazeigte mir die VM-Argumente, die in meinem Fall den -Xmx-Wert enthielten, was alles war, was ich brauchte.
xdhmoore
66

jvmtop ist ein Befehlszeilentool, das eine Live-Ansicht mit verschiedenen Metriken, einschließlich Heap, bietet.

Beispielausgabe des VM-Übersichtsmodus:

 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
MRalwasser
quelle
Es ist in der Tat ein großartiges Tool, eine Art Htop, aber mit Metriken von jstat. Danke für den Vorschlag, @MRalwasser.
oski86
65

Dieser Befehl zeigt die konfigurierten Heap-Größen in Bytes an.

java -XX:+PrintFlagsFinal -version | grep HeapSize

Es funktioniert auch mit Amazon AMI auf EC2.

Atma
quelle
26
Dies beantwortet nicht die Frage, wie speziell die Heap-Nutzung eines Prozesses überprüft werden soll. Der Befehl hier listet die JVM-Standardeinstellungen für alle Prozesse auf.
Madbreaks
10
Es ist jedoch eine sehr hilfreiche Antwort für mich, über die Google-Suche auf diese Seite zu gelangen, um die globale Heap-Größe zu ermitteln.
Johan
@jumping_monkey nicht indirekt, falsch. Wenn das, was Sie sagen, wahr ist, sollte die Antwort bearbeitet werden oder Sie können eine neue Antwort hinzufügen.
Madbreaks
42

Versuchen Sie dies, es funktionierte in Ubuntu und RedHat:

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

Für Windows:

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

Für Mac

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

Die Ausgabe all dieser Befehle ähnelt der folgenden Ausgabe:

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)

Teilen Sie den Wert durch (1024 * 1024), um die Größe in MB zu ermitteln.

Padippist
quelle
Wie finde ich die Speichernutzung getrennt durch Heap, Permsize, ... eines bestimmten Java-Prozesses durch PID?
Gary Gauh
3
@GaryGauh Dies ist die Standardgröße des Heapspeichers. Um die Verwendung der laufenden Anwendung zu finden, sollten Sie dies im Code tun, oder Sie können jconsole verwenden. Ich weiß, dass es auch viele andere Möglichkeiten geben sollte.
Padippist
2
Verwenden Sie jstat -gc <vmid>zum Ausführen von Anwendungen.
Micha Wiedenmann
27

Ohne JMX, wie es die meisten Tools verwenden, können Sie es nur verwenden

jps -lvm

und schließen Sie, dass die Einstellungen aus den Befehlszeilenoptionen stammen.

Ohne JMX können Sie standardmäßig keine dynamischen Informationen abrufen, aber Sie können dazu Ihren eigenen Dienst schreiben.

Übrigens: Ich bevorzuge VisualVM anstelle von JConsole.

Peter Lawrey
quelle
25

Es gibt ein Kommandozeilen-Tool mit einem visuellen Aspekt - jvm-mon . Es ist ein JVM-Überwachungstool für die Befehlszeile, das nicht mehr funktioniert:

  • Heap-Nutzung, Größe und max
  • JVM-Prozesse
  • CPU- und GC-Nutzung
  • Obergewinde

Die Metriken und Diagramme werden aktualisiert, während das Tool geöffnet ist.

Stichprobe: jvm-mon

Andrejs
quelle
1
Nur um zu beachten, dass jvm-mon nur für Java8 läuft
tmanolatos
1
^ Es gibt eine neue Version, die jetzt auch Java 11 unterstützt.
Andrejs
11

Spät auf der Party, aber eine sehr einfache Lösung ist die Verwendung des Skripts jpsstat.sh. Es bietet einen einfachen Live- Stromspeicher , maximalen Speicher und Details zur CPU-Nutzung .

  • Goto GitHub Projekt und laden Sie die jpsstat.sh Datei
  • Klicken Sie mit der rechten Maustaste auf jpsstat.sh und gehen Sie zur Registerkarte Berechtigungen, um sie ausführbar zu machen
  • Führen Sie nun das Skript mit dem folgenden Befehl aus ./jpsstat.sh

Hier ist die Beispielausgabe des Skripts -

=====  ======  =======  =======  =====
 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
amarjeetAnand
quelle
scheint unter SUSE Linux nicht sofort zu funktionieren (Zeile 38: Deklarieren: -A: ungültige Option)
Chris
Klingt so, als ob Sie einen Fehler in der assoziativen Array-Deklaration erhalten, für den bash> = 4 erforderlich ist. Ein weiteres Problem kann darin liegen, dass das Skript als "sh jpsstat.sh" ausgeführt wird. Versuchen Sie in diesem Fall, das Skript als "./jpsstat.sh" auszuführen.
AmarjeetAnand
9

In meinem Fall musste ich die Flags in einem Docker-Container überprüfen, der nicht über die meisten grundlegenden Dienstprogramme verfügte (ps, pstree ...).

Mit habe jpsich die PID der JVM ausgeführt (in meinem Fall 1) und dann mit habe jcmd 1 VM.flagsich die Flags von der laufenden JVM erhalten.

Es hängt davon ab, welche Befehle Ihnen zur Verfügung stehen, aber dies kann jemandem helfen. :) :)

Froblesmartin
quelle
8

Ab Java8 können Sie den folgenden Befehl verwenden:

jcmd JAVA_PROCESS_IDGC.heap_info

Sie können sich auf die Summe des gesamten und des verwendeten Speichers der Ausgabe beziehen.

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

Weitere Informationen zum Befehl jcmd finden Sie unter folgendem Link: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html

Vaibhav Gupta
quelle
1
Sie müssen Ihren Kommentar korrigieren. GC.heap_info ist in Java 9 und höher verfügbar. Es ist nicht in Java 8 verfügbar. Einen
Pavel Molchanov
@PavelMolchanov Ich kann den Befehl in jdk1.8.0_172 verwenden. /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/bin/jcmd 98270 GC.heap_info. Bitte, wenn Sie dürfen, fügen Sie die Informationen zum verwiesenen Thread hinzu, da ich momentan nicht genug Ruf habe, um dort einen Kommentar hinzuzufügen.
Vaibhav Gupta
Benutzt du einen Mac? Verwenden Sie Oracle JDK? Ich weiß nicht, wie es in Ihrem jdk1.8.0_172 verfügbar sein kann. Oracle hat diese Funktion nur in Java 9 und höher dokumentiert: docs.oracle.com/javase/9/tools/jcmd.htm . Es ist nicht in der Oracle JDK-Dokumentation für Java 8 enthalten. Es wird nicht in dem Link erwähnt, den Sie unten angegeben haben: docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/…
Pavel Molchanov
Noch eine Frage. Überprüfen Sie in Ihrem Beispiel die JDK-Version, auf der der Prozess 98270 ausgeführt wird. jcmd erhält verfügbare Befehle von der JVM des Prozesses (in Ihrem Fall 98270). Wenn der Prozess 98270 mit einem anderen JDK (JDK 9 oder höher) ausgeführt wird, wird der Befehl GC.heap_info auch in JCMD selbst von Java 8 verfügbar angezeigt. Die verfügbaren Befehle können für verschiedene Prozesse unterschiedlich sein. Um verfügbare Befehle zu erhalten, führen Sie Folgendes aus: jcmp <PID> help.
Pavel Molchanov
1
FWIW GC.heap_infoist definitiv auch in OpenJDK 8 verfügbar. Vielleicht nur in neueren Versionen? Ich benutze dieses: 8u191-b12-2ubuntu0.18.04.1
Per Lundberg
7

Jeder Ansatz sollte Ihnen ungefähr die gleiche Anzahl geben. Es ist immer eine gute Idee, den Heap -X..m -X..xfür alle Generationen zuzuweisen . Sie können dann garantieren und auch ps ausführen, um zu sehen, welche Parameter übergeben wurden und daher verwendet werden.

Für die tatsächliche Speichernutzung können Sie VIRT (zugewiesen und gemeinsam genutzt) und RES (tatsächlich verwendet) grob mit den jstat-Werten vergleichen:

Für Java 8 siehe jstat, denn diese Werte bedeuten tatsächlich. Angenommen, Sie führen eine einfache Klasse ohne mmap- oder Dateiverarbeitung aus.

$ 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

Max :

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

(ungefähr in der Nähe und unterhalb des VIRT-Speichers)

Max (Min, Gebraucht):

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

(ungefähr in der Nähe des RES-Speichers)

"Zitiere mich nicht dazu", aber VIRT mem liegt ungefähr in der Nähe des zugewiesenen maximalen Speichers oder darüber, aber solange der verwendete Speicher im physischen Speicher frei / verfügbar ist, löst JVM keine Speicherausnahme aus. Tatsächlich wird der maximale Speicher beim JVM-Start nicht einmal mit dem physischen Speicher verglichen, selbst wenn das Betriebssystem ausgeschaltet ist. Eine bessere Erklärung dessen, was der virtuelle Speicher tatsächlich von einem Java-Prozess verwendet, wird hier erläutert .

kisna
quelle
4

Holen Sie sich zuerst die Prozess-ID, die erste Nummer aus dem aufgelisteten Prozess, aus einer der folgenden Quellen: (oder verwenden ps aux | grep javaSie einfach , wenn Sie dies bevorzugen)

jps -lvm

Verwenden Sie dann hier die Prozess-ID:

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

Die Verwendung eines topBefehls ist der einfachste Weg, um die Speichernutzung des Programms zu überprüfen. RESDie Spalte zeigt den realen physischen Speicher, der von einem Prozess belegt wird.

Für meinen Fall hatte ich eine 10g-Datei in Java gelesen und jedes Mal, wenn ich eine Ausnahme von outOfMemory bekam. Dies geschah, als der Wert in der RESSpalte den in der -XmxOption festgelegten Wert erreichte . Durch Erhöhen des Speichers mit der -XmxOption ging dann alles in Ordnung.

M. Mashaye
quelle
3
Der Befehl top zeigt an, wie viel Betriebssystem der JVM zugewiesen wird. Dieser Typ fragt, wie wir die Heap-Speicherplatznutzung in JVM sehen können. JVM verwendet 10g. Dies bedeutet nicht, dass der reale Heap-Speicherplatz mit 10g-Daten gefüllt ist, da jvm den Speicher fast nie vom Heap an das Betriebssystem zurückgibt, bis Sie den Prozess beenden.
Linehrr
2

In Bezug auf die Größe des Java-Heapspeichers können Sie unter Linux verwenden

ps aux | grep java

oder

ps -ef | grep java

Suchen Sie nach -Xms, -Xmx, um die angegebene anfängliche und maximale Heap-Größe zu ermitteln.

Wenn jedoch -Xms oder -Xmx für den Java-Prozess, an dem Sie interessiert sind, nicht vorhanden ist, bedeutet dies, dass Ihr Java-Prozess die Standard-Heap-Größen verwendet. Mit dem folgenden Befehl können Sie die Standardgrößen ermitteln.

java -XX:+PrintFlagsFinal -version | grep HeapSize

oder ein bestimmtes jvm zum Beispiel

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

und suchen Sie nach InitialHeapSize und MaxHeapSize, die in Bytes angegeben sind.

Yuci
quelle
1

Wenn Sie jrockit verwenden, versuchen Sie es mit dem Befehlszeilentool jrcmd. Beispielsweise:

$ 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)

Verwenden Sie für weitere Befehle wie heap_diagnostics "jrcmd help", um sie aufzulisten.

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

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

Beispiel-O / P des obigen Befehls

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).

Weitere Informationen hierzu finden Sie unter http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html

Pravin
quelle
1

Es gibt kein solches Werkzeug bis jetzt den Heap - Speicher in dem Format zu drucken , wie Sie verlangten Den einzigen und einzigen Weg , um Druck ein Java - Programm mit Hilfe von Laufzeit - Klasse zu schreiben ist ,

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

}}

Referenz: https://viralpatel.net/blogs/getting-jvm-heap-size-used-memory-total-memory-using-java-runtime/

Gowtham Prasath
quelle
das ist falsch. jmap -heap <pid> gibt diese Information
vsingh
0

Suchen Sie die Prozess-ID Ihres Webapp / Java-Prozesses von oben. Verwenden Sie jmap heap, um die Heap-Zuordnung abzurufen. Ich habe dies auf AWS-Ec2 auf elastische Bohnenstange getestet

Sie können im Bild unten maximal 3 GB Heap für die Anwendung sehen

Geben Sie hier die Bildbeschreibung ein

vsingh
quelle