2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Das JVM-Parametereinstellungsformat des Spring Boot-Programms (der Tomcat-Start wird direkt zur Datei catalina.sh im bin-Verzeichnis hinzugefügt):
java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar microservice-eureka-server.jar
abschließend:
Je kleiner die Einstellung -Xss ist, desto kleiner ist der Zählwert, was bedeutet, dass einem Thread-Stapel weniger Stapelrahmen zugewiesen werden können, aber die Anzahl der Threads, die geöffnet werden können, ist für die JVM insgesamt höher.
-Xss: Stapelgröße jedes Threads, Standard 1 MB
-Xms: Legen Sie die anfänglich verfügbare Größe des Heaps fest. Der Standardwert ist 1/64 des physischen Speichers
-Xmx: Legen Sie die maximal verfügbare Größe des Heaps fest. Der Standardwert ist 1/4 des physischen Speichers
-Xmn: Größe der neuen Generation
-XX:NewRatio: Der Standardwert 2 bedeutet, dass die neue Generation 1/2 der alten Generation und 1/3 des gesamten Heap-Speichers ausmacht.
-XX:SurvivorRatio: Der Standardwert 8 bedeutet, dass ein Survivor-Bereich 1/8 des Eden-Speichers belegt, also 1/10 des Speichers der neuen Generation.
Es gibt zwei JVM-Parameter für Metaspace: -XX:MetaspaceSize=N und -XX:MaxMetaspaceSize=N
-XX: MaxMetaspaceSize: Legen Sie die maximale Metaspace-Größe fest. Der Standardwert ist -1, was bedeutet, dass es keine Begrenzung gibt oder nur durch die lokale Speichergröße begrenzt ist.
-XX: MetaspaceSize: Geben Sie den anfänglichen Schwellenwert für den Metaspace an, um Fullgc auszulösen (es gibt keine feste Anfangsgröße für Metaspace), in Bytes. Der Standardwert beträgt etwa 21 MB. Wenn dieser Wert erreicht ist, wird der vollständige GC für das Entladen des Typs ausgelöst Der Kollektor passt diesen Wert an: Wenn viel Speicherplatz freigegeben wird, verringern Sie den Wert entsprechend. Wenn nur wenig Speicherplatz freigegeben wird, erhöhen Sie den Wert entsprechend, ohne -XX:MaxMetaspaceSize (falls festgelegt) zu überschreiten. Dies hat eine andere Bedeutung als der Parameter -XX:PermSize in früheren JDK-Versionen. -XX:PermSize stellt die anfängliche Kapazität der permanenten Generation dar.
Da die Größenänderung des Metaraums eine vollständige GC erfordert, ist dies ein sehr kostspieliger Vorgang. Wenn beim Starten der Anwendung eine große Anzahl von vollständigen GCs auftritt, liegt dies normalerweise an der Größenänderung der permanenten Generation oder des Metaraums Im Allgemeinen wird empfohlen, in den JVM-Parametern MetaspaceSize und MaxMetaspaceSize auf denselben Wert und einen größeren Wert als den Anfangswert festzulegen. Bei einer Maschine mit 8G physischem Speicher setze ich im Allgemeinen beide Werte auf 256 MB.
In der virtuellen HotSpot-Maschine kann das Layout der im Speicher gespeicherten Objekte in drei Bereiche unterteilt werden: Objektkopf (Header), Instanzdaten (Instanzdaten) und Ausrichtungsauffüllung (Padding). Der Objektheader der virtuellen HotSpot-Maschine enthält zwei Teile von Informationen. Der erste Teil wird zum Speichern der Laufzeitdaten des Objekts selbst verwendet, z. B. Hash-Code (HashCode), Alter der GC-Generierung, Sperrstatus-Flag und vom Thread gehaltene Sperre , voreingenommene Thread-ID, bevorzugte Zeitstempel usw. Der andere Teil des Objektheaders ist der Typzeiger, der der Zeiger des Objekts auf seine Klassenmetadaten ist. Die virtuelle Maschine verwendet diesen Zeiger, um zu bestimmen, zu welcher Klasse das Objekt gehört.
1. Die Verwendung von 32-Bit-Zeigern (der tatsächliche Speicher verwendet 64-Bit) in HotSpot auf einer 64-Bit-Plattform verbraucht etwa 1,5-mal mehr Speicher. Die Verwendung größerer Zeiger zum Verschieben von Daten zwischen Hauptspeicher und Cache nimmt eine größere Bandbreite in Anspruch Gleichzeitig wird auch GC stärker unter Druck geraten
2. Um den Speicherverbrauch auf 64-Bit-Plattformen zu reduzieren, aktivieren Sie die Zeigerkomprimierungsfunktion
3. In JVM unterstützen 32-Bit-Adressen bis zu 4 GB Speicher (2 bis 32 Potenzen). Dies kann optimiert werden, indem der Objektzeiger beim Speichern im Heap-Speicher komprimiert und codiert und nach dem Herausnehmen decodiert wird zum CPU-Register (der Objektzeiger befindet sich im Heap) Es sind 32 Bit, 35 Bit im Register, 2 hoch 35 = 32G), sodass der JVM nur größere Speicherkonfigurationen (weniger als oder gleich 32G) unterstützen kann 32-Bit-Adressen
4. Wenn der Heap-Speicher weniger als 4 GB beträgt, muss die Zeigerkomprimierung nicht aktiviert werden. Der JVM entfernt die hohe 32-Bit-Adresse direkt, dh er verwendet den niedrigen virtuellen Adressraum.
5. Wenn der Heap-Speicher größer als 32 GB ist, wird der Komprimierungszeiger ungültig und 64 Bit (d. H. 8 Byte) müssen das Java-Objekt adressieren. Dies führt zu dem Problem 1, daher ist es besser, dies nicht zu tun Der Heap-Speicher ist größer als 32 GB.
In diesem Fall kann die JVM den Speicherort des Objekts optimieren, indem er den Escape-Analyseparameter (-XX:+DoEscapeAnalysis) aktiviert, sodass er zuerst durch Skalarersetzung zugewiesen wird (Zuweisung auf dem Stapel). nach JDK7 standardmäßig aktiviert. Wenn Sie möchten, deaktivieren Sie es mithilfe von Parametern (-XX:-DoEscapeAnalysis).
Skalare Ersetzung: Wenn durch Escape-Analyse festgestellt wird, dass auf das Objekt nicht extern zugegriffen wird und das Objekt weiter zerlegt werden kann, erstellt die JVM das Objekt nicht, sondern zerlegt die Objektmitgliedsvariablen in mehrere von dieser Methode verwendete Mitgliedsvariablen und Ersetzen Sie sie, indem Sie Speicherplatz auf dem Stapelrahmen oder Register zuweisen, sodass keine ausreichende Speicherzuweisung für das Objekt vorhanden ist, da kein großer zusammenhängender Speicherplatz vorhanden ist. Aktivieren Sie skalare Ersetzungsparameter (-XX:+EliminateAllocations), die nach JDK7 standardmäßig aktiviert sind.
Skalare und aggregierte Mengen: Ein Skalar ist eine Größe, die nicht weiter zerlegt werden kann, und der grundlegende Datentyp von JAVA ist ein Skalar (z. B. int, long und andere grundlegende Datentypen und Referenztypen usw.). ist eine Menge, die weiter zersetzt werden kann, und diese Menge wird Polymerisationsmenge genannt. In JAVA sind Objekte Aggregate, die weiter zerlegt werden können.
Große Objekte sind Objekte, die viel kontinuierlichen Speicherplatz benötigen (z. B. Zeichenfolgen und Arrays). Der JVM-Parameter -XX:PretenureSizeThreshold kann die Größe großer Objekte festlegen. Wenn das Objekt die festgelegte Größe überschreitet, gelangt es direkt in die alte Generation und nicht in die junge Generation. Dieser Parameter ist nur unter den beiden Kollektoren Serial und ParNew gültig.
Legen Sie beispielsweise die JVM-Parameter fest: -XX:PretenureSizeThreshold=1000000 (Einheit ist Bytes) -XX:+UseSerialGC Wenn Sie das erste Programm oben ausführen, werden Sie feststellen, dass das große Objekt direkt in die alte Generation eintritt.
Warum muss das so sein?
Um Kopiervorgänge bei der Speicherzuweisung für große Objekte zu vermeiden und die Effizienz zu verringern.
Im Survivor-Bereich, in dem das Objekt derzeit platziert ist (einer der Bereiche, der s-Bereich, in dem das Objekt platziert ist), ist die Gesamtgröße eines Stapels von Objekten größer als 50 % der Speichergröße dieses Survivor-Bereichs (-XX :TargetSurvivorRatio kann angegeben werden), dann ist es zu diesem Zeitpunkt größer als Objekte, die dem maximalen Alter dieses Stapels von Objekten entsprechen. Beispielsweise gibt es einen Stapel von Objekten im Survivor-Bereich Die Summe mehrerer Altersobjekte mit Alter 1 + Alter 2 + Alter n übersteigt 50 % des Survivor-Bereichs. Zu diesem Zeitpunkt werden alle Objekte mit Alter n (einschließlich) und höher in die alte Generation aufgenommen. Diese Regel hofft tatsächlich, dass Objekte, die möglicherweise lange überleben, so schnell wie möglich ins Alter gelangen. Der objektdynamische Altersbeurteilungsmechanismus wird im Allgemeinen nach einem geringfügigen GC ausgelöst.
Vor jedem kleineren GC in der jungen Generation berechnet die JVM den verbleibenden freien Speicherplatz in der alten Generation.
Wenn der verfügbare Platz kleiner ist als die Summe der Größen aller vorhandenen Objekte der jungen Generation (einschließlich Müllobjekte)
Es wird geprüft, ob der Parameter „-XX:-HandlePromotionFailure“ (standardmäßig in jdk1.8 festgelegt) gesetzt ist.
Wenn dieser Parameter vorhanden ist, wird geprüft, ob die verfügbare Speichergröße in der alten Generation größer ist als die durchschnittliche Größe der Objekte, die nach jedem vorherigen Minor-GC in die alte Generation eingetreten sind.
Wenn das Ergebnis des vorherigen Schritts kleiner ist als oder die oben genannten Parameter nicht festgelegt sind, wird ein vollständiger GC ausgelöst und die alte Generation und die junge Generation werden zusammengeführt, sofern immer noch nicht genügend Speicherplatz zum Speichern neuer Daten vorhanden ist Objekte nach dem Recycling wird „OOM“ auftreten.
Wenn die Größe der verbleibenden überlebenden Objekte, die nach dem kleineren GC in die alte Generation verschoben werden müssen, natürlich immer noch größer ist als der verfügbare Platz in der alten Generation, wird auch der vollständige GC ausgelöst. Nach dem vollständigen GC, falls vorhanden Ist nach dem Minor-GC immer noch kein Platz für die überlebenden Objekte vorhanden, tritt ebenfalls „OOM“ auf
Mehrere Hauptklassenlader von Tomcat:
commonLoader: Tomcats grundlegendster Klassenlader. Auf Klassen im Ladepfad kann vom Tomcat-Container selbst und jeder Webanwendung zugegriffen werden.
catalinaLoader: Der private Klassenlader des Tomcat-Containers. Die Klassen im Ladepfad sind für die Webanwendung nicht sichtbar.
sharedLoader: Ein von jeder Webanwendung gemeinsam genutzter Klassenlader. Die Klassen im Ladepfad sind für alle Webanwendungen sichtbar, jedoch nicht für den Tomcat-Container.
WebappClassLoader: Der private Klassenlader jeder Webapp ist nur für die aktuelle Webapp sichtbar, z. B. zum Laden verwandter Klassen in einem Kriegspaket. Jede Kriegspaketanwendung verfügt über einen eigenen WebappClassLoader, um eine gegenseitige Isolierung zu erreichen, z. B. für unterschiedliche Kriegspakete Anwendungen Es werden verschiedene Federversionen eingeführt, damit die Implementierung ihre jeweiligen Federversionen laden kann.