Was ist die Standardstapelgröße, kann sie wachsen, wie funktioniert sie mit der Speicherbereinigung?

75

Ich verstehe, dass jeder Thread seinen eigenen hat stack. Primitive Typen und Referenzen werden auf dem Stapel gespeichert, und es wird kein Objekt auf dem Stapel gespeichert.

Meine Fragen sind:

  • Wie viel kann ein Stapel wachsen? (wie bei den Parametern - Xmsund - Xmx)
  • Können wir sein Wachstum begrenzen?
  • Hat der Stapel einen Standard-Minimal- und Maximalwert?
  • Wie funktioniert die Speicherbereinigung auf dem Stapel?
Batty
quelle
Nur eine kleine Bemerkung für Leute, die dies lesen: Escape-Analysis (Java 6 Update 21 und höher) ermöglicht das Speichern von Objekten im Stapel. Weniger Arbeit für Müllsammler.
miracle_the_V
Teilweise Dup von stackoverflow.com/questions/6020619/…
Vadzim
GC funktioniert nicht auf dem Stapel. Sie können keine Dinge auf dem Stapel erstellen, daher gibt es nichts zu sammeln - JVM selbst legt Dinge in den Stapel und entfernt sie nach Bedarf. "Müll", der gesammelt wird, sind Instanzen Ihrer Objekte, die Sie erstellt haben.
8.

Antworten:

93

Wie viel kann ein Stapel wachsen?

Sie können eine VM-Option mit dem Namen verwenden ss, um die maximale Stapelgröße anzupassen. Eine VM-Option wird normalerweise mit -X {Option} übergeben. Sie können also java -Xss1Mdie maximale Stapelgröße auf 1 MB festlegen.

Jeder Thread hat mindestens einen Stapel. Einige Java Virtual Machines (JVM) fassen den Java-Stack (Java-Methodenaufrufe) und den nativen Stack (native Methodenaufrufe in VM) in einem Stapel zusammen und führen das Abwickeln des Stapels mithilfe eines Managed to Native-Frames durch, der als M2NFrame bezeichnet wird. Einige JVMs halten zwei Stapel getrennt. In Xssden meisten Fällen wird die Größe des Java-Stacks festgelegt.

Für viele JVMs legen sie unterschiedliche Standardwerte für die Stapelgröße auf verschiedenen Plattformen fest.

Können wir dieses Wachstum begrenzen?

Wenn ein Methodenaufruf auftritt, wird ein neuer Stapelrahmen auf dem Stapel dieses Threads erstellt. Der Stapel enthält lokale Variablen, Parameter, Rücksprungadresse usw. In Java können Sie niemals ein Objekt auf den Stapel legen, sondern nur die Objektreferenz auf dem Stapel speichern. Da Array auch ein Objekt in Java ist, werden Arrays auch nicht im Stapel gespeichert. Wenn Sie also die Anzahl Ihrer lokalen primitiven Variablen und Parameter reduzieren, indem Sie sie in Objekte gruppieren, können Sie den Speicherplatz auf dem Stapel reduzieren. Tatsächlich wirkt sich die Tatsache, dass wir Objekte nicht explizit auf den Java-Stapel legen können, auf die Leistung aus (Cache-Fehler).

Hat der Stapel einen Standard-Minimalwert oder einen Standard-Maximalwert?

Wie ich bereits sagte, sind verschiedene VMs unterschiedlich und können sich über Versionen ändern. Siehe hier .

Wie funktioniert die Speicherbereinigung auf dem Stapel?

Garbage Collections in Java sind ein heißes Thema. Die Speicherbereinigung zielt darauf ab, nicht erreichbare Objekte auf dem Heap zu sammeln . Das braucht also eine Definition von "erreichbar". Alles auf dem Stapel ist Teil der Root-Set-Referenzen in GC. Alles, was von jedem Stapel jedes Threads aus erreichbar ist, sollte als live betrachtet werden. Es gibt einige andere Stammsatzreferenzen, wie Thread-Objekte und einige Klassenobjekte.

Dies ist nur eine sehr vage Verwendung von Stack auf GC. Derzeit verwenden die meisten JVMs einen Generations-GC. Dieser Artikel enthält eine kurze Einführung in Java GC. Und kürzlich habe ich einen sehr guten Artikel über den GC auf .net gelesen . Der GC auf oracle jvm ist ziemlich ähnlich, daher denke ich, dass Ihnen das auch helfen könnte.

StarPinkER
quelle
5
Gute Antwort. Ich möchte nur hinzufügen, dass ich die Standardeinstellungen als konservativ empfinde und sie alle Arten von Bereitstellungen abdecken sollen. Aber meiner Erfahrung nach hatte ich selbst bei großen Anwendungen (über 500.000 Codezeilen), die auf Anwendungsservern ausgeführt wurden, noch nie einen StackOverflow-Fehler, selbst wenn der Stapel auf 256 KB (-Xss256 KB) eingestellt war. Stellen Sie sich einen App-Server mit 70 laufenden Threads mit dem Standard-1-MB-Stack vor, das sind zusätzliche 70 MB für den Prozess.
Brettw
5
java -Xss 100M -jar testing.jarwarf den Fehler "Ungültige Thread-Stapelgröße: -Xss Fehler: Java Virtual Machine konnte nicht erstellt werden." hat aber gut java -Xss100M -jar testing.jarfunktioniert. Ausführen von Windows 10 64-Bit mit Java "1.8.0_112". Sollte Ihr Beitrag bearbeitet werden, um den Platz zu entfernen?
Aaron Franke
Für Leute, die Maven benutzen, sieht das so aus: gist.github.com/belkacemlahouel/…
belka
1
"In Java kann man niemals ein Objekt auf einen Stapel legen ... wirkt sich auf die Leistung aus." Dies ist nicht wahr! HotSpot weist Objekte auf dem Stapel zu, wenn die Escape-Analyse ergibt, dass sie nirgendwo anders erreichbar sind. Dies verbessert die Cache-Lokalität, spart jedoch noch mehr GC-Kosten. Dies ist ein Hauptgrund für die hervorragende Leistung von Java.
Aleksandr Dubinsky
13

Wie Sie sagen, werden lokale Variablen und Referenzen auf dem Stapel gespeichert. Wenn eine Methode zurückkehrt, wird der Stapelzeiger einfach dorthin zurückgesetzt, wo er vor dem Start der Methode war, dh alle lokalen Daten werden "vom Stapel entfernt". Daher ist auf dem Stapel keine Speicherbereinigung erforderlich, die nur im Heap erfolgt.

So beantworten Sie Ihre spezifischen Fragen:

  • In dieser Frage erfahren Sie, wie Sie die Stapelgröße erhöhen können.
  • Sie können das Stapelwachstum begrenzen durch:
    • Gruppieren vieler lokaler Variablen in einem Objekt: Dieses Objekt wird im Heap gespeichert und nur die Referenz wird auf dem Stapel gespeichert
    • Begrenzen Sie die Anzahl der verschachtelten Funktionsaufrufe (normalerweise ohne Rekursion).
  • Für Windows beträgt die Standardstapelgröße 320 KB für 32 Bit und 1024 KB für 64 Bit (siehe diesen Link) .
Vincent van der Weele
quelle
Obwohl das Objekt, das lokale Variablen gruppiert, im Heap gespeichert ist, ist dieses Objekt zum Zeitpunkt der Rückgabe der Methode verschwunden. JVM führt eine Art Objekt-Deferenzierung durch. Korrigieren Sie mich, wenn ich falsch
liege
1
@asgs Hier setzt die Garbage Collection an. Wenn die lokale Variable tatsächlich der einzige Verweis auf das Objekt war, wird das Objekt irgendwann nach der Rückkehr der Methode von GC entfernt. Wenn die Methode einen externen Verweis auf das Objekt hinzugefügt hat, wird dieser von GC nicht entfernt.
Vincent van der Weele