[Einleitung] Wir schreiben das Jahr 2017, aber zwei Dinge sind für die meisten Entwickler immer noch ein Rätsel – Garbage Collection und das andere Geschlecht (Programmierer werden wieder ausgelacht). Da ich über Letzteres nicht viel weiß, dachte ich, ich versuche, über Ersteres zu sprechen.
Wir schreiben das Jahr 2017, aber zwei Dinge sind für die meisten Entwickler immer noch ein Rätsel – Garbage Collection und das andere Geschlecht (Programmierer werden wieder ausgelacht). Da ich über Letzteres nicht viel weiß, werde ich versuchen, über Ersteres zu sprechen. Insbesondere mit der Einführung von Java 8 haben in diesem Bereich viele große Änderungen und Verbesserungen stattgefunden, von denen die wichtigste ist Entfernung der persistenten Generierung (PermGen) und einige aufregende neue Optimierungen (die später erwähnt werden).
Apropos Garbage Collection: Viele Menschen verstehen das Konzept und wenden es in der täglichen Programmierung an. Dennoch gibt es vieles, was wir nicht ganz verstehen, und daher kommt der Schmerz. Das größte Missverständnis über die JVM besteht darin, dass sie nur einen Garbage Collector hat, obwohl sie tatsächlich über vier verschiedene Collectors verfügt, von denen jeder seine eigenen Stärken und Schwächen hat. Die JVM wählt nicht automatisch eines aus, es liegt an Ihnen und mir, da unterschiedliche Collectors erhebliche Unterschiede im Durchsatz und bei den Anwendungspausenzeiten verursachen können.
Diesen vier Sammlungsalgorithmen ist gemeinsam, dass sie alle generationsübergreifend sind, was bedeutet, dass sie den verwalteten Heap in mehrere Regionen aufteilen. Es wird davon ausgegangen, dass sich viele Objekte im Heap befinden Der Lebenszyklus ist sehr kurz und kann schnell recycelt werden. Es gab viele Einführungen in dieses Thema, daher möchte ich hier direkt auf diese verschiedenen Algorithmen sowie ihre Stärken und Schwächen eingehen.
Der serielle Collector ist der einfachste, den Sie nicht einmal in Betracht ziehen werden, da er hauptsächlich für Single-Thread-Umgebungen (wie 32-Bit oder Windows) gedacht ist ein kleinerer Haufen. Dieser Kollektor friert alle Anwendungsthreads ein, wenn er funktioniert, was die Verwendung durch serverseitige Anwendungen völlig unmöglich macht.
So verwenden Sie es: Sie können den JVM-Parameter -XX:+UseSerialGC aktivieren, um es zu verwenden.
Der nächste ist der Parallelkollektor (Parallel-Kollektor). Dies ist der Standardkollektor der JVM. Wie der Name schon sagt, besteht sein größter Vorteil darin, dass mehrere Threads zum Scannen und Komprimieren des Heaps verwendet werden. Der Nachteil besteht darin, dass der Anwendungsthread angehalten wird, unabhängig davon, ob es sich um einen Minor-GC oder einen vollständigen GC handelt. Der Parallelkollektor eignet sich am besten für Anwendungen, die Pausen tolerieren und versuchen, den durch den Kollektor verursachten CPU-Overhead zu reduzieren.
Nach dem Parallelkollektor folgt der CMS-Kollektor (Concurrent-Mark-Sweep). Dieser Algorithmus verwendet mehrere Threads (gleichzeitig), um den Heap zu scannen und Objekte zu markieren, die nicht mehr verwendet werden und recycelt werden können (Sweep). Dieser Algorithmus wechselt in zwei Situationen in einen „Stop the World“-Modus: Bei der anfänglichen Markierung des Stammobjekts (Thread-Eintrittspunkt in der alten Generation oder statischVariable) können Objekte das sein erreicht wurden) und wenn dieser Algorithmus gleichzeitig ausgeführt wird, ändert die Anwendung den Status des Heaps, sodass sie zurückgehen und erneut bestätigen muss, dass die von ihr markierten Objekte korrekt sind.
Das größte Problem bei der Verwendung dieses Sammlers besteht darin, dass Sie auf Werbefehler stoßen, was sich auf die Situation bezieht, in der es beim Recycling der neuen Generation und der alten Generation zu Wettbewerbsbedingungen kommt. Wenn der Sammler junge Objekte zur alten Generation befördern muss und zu diesem Zeitpunkt kein zusätzlicher Speicherplatz in der alten Generation vorhanden ist, kann er zunächst nur einen vollständigen STW-GC (Stop The World) durchführen. Dies ist die richtige Situation was CMS vermeiden möchte. Um sicherzustellen, dass dies nicht geschieht, müssen Sie entweder die Größe der alten Generation erhöhen (oder die Größe des gesamten Heaps erhöhen) oder dem Kollektor einige Hintergrundthreads zuweisen, damit dieser mit der Geschwindigkeit der Objektzuweisung konkurrieren kann .
Ein weiterer Nachteil dieses Algorithmus besteht darin, dass er mehr CPU-Ressourcen verbraucht als der Parallelkollektor. Er verwendet mehrere Threads zum Scannen und Recycling, sodass die Anwendung weiterhin einen höheren Durchsatz bieten kann. Für die meisten Programme mit langer Laufzeit ist die Unterbrechung der Anwendung sehr schädlich. Zu diesem Zeitpunkt können Sie die Verwendung des CMS-Recyclers in Betracht ziehen. Dieser Algorithmus ist jedoch standardmäßig nicht aktiviert. Sie müssen XX:+UseConcMarkSweepGC angeben, um es zu aktivieren. Angenommen, Ihr Heap ist kleiner als 4G und Sie möchten mehr CPU-Ressourcen zuweisen, um eine Anwendungsunterbrechung zu vermeiden, dann ist dies der Collector, den Sie wählen sollten. Wenn der Heap jedoch größer als 4G ist, bevorzugen Sie möglicherweise die Verwendung des letzten Heaps – des G1-Kollektors.
Der G1-Kollektor (Garbage First) wurde erstmals in JDK 7, Update 4, eingeführt. Sein Designziel besteht darin, Heaps mit mehr als 4 GB besser zu unterstützen. Der G1-Kollektor unterteilt den Heap in Bereiche mit einer Größe von 1 MB bis 32 MB und scannt diese mithilfe mehrerer Hintergrundthreads. Der G1-Kollektor scannt zuerst die Bereiche mit dem meisten Müll, daher der Name (Garbage first). Dieser Collector kann mit dem Flag -XX:UseG1GC aktiviert werden.
Diese Strategie verringert die Wahrscheinlichkeit, dass der Heap aufgebraucht ist, bevor der Hintergrundthread die nutzlosen Objekte gescannt hat. In diesem Fall muss der Collector die Anwendung anhalten, was zu einem STW-Recycling führt. Ein weiterer Vorteil von G1 besteht darin, dass der Heap immer komprimiert wird, während der CMS-Kollektor dies nur während einer vollständigen GC tut.
In den letzten Jahren war Dadu ein umstrittener Bereich vom Single-Machine-Single-JVM-Modell zu Single-Machine-Multi-JVM-Microservices und Komponentisierung 🎜>Architektur. Dies ist auf eine Reihe von Faktoren zurückzuführen, darunter die Isolierung von Anwendungskomponenten, die Vereinfachung der Bereitstellung und die Vermeidung des Mehraufwands durch das erneute Laden von Anwendungsklassen in den Speicher (dies wurde in Java 8 verbessert). Die größte Hoffnung besteht jedoch darin, lange „Stop-the-World“-Pausen in großen GCs zu vermeiden (die bei einer großen Sammlung mehrere Sekunden dauern). Containertechnologien wie Docker beschleunigen diesen Prozess ebenfalls. Sie ermöglichen Ihnen die einfache Bereitstellung mehrerer Anwendungen auf derselben physischen Maschine.
Java 8- und G1-Kollektor Eine großartige Optimierung, die in Java 8 Update 20 eingeführt wurde, ist die
String--Deduplizierung). Da Zeichenfolgen (einschließlich ihres internen char[]array) den größten Teil des Heap-Speicherplatzes belegen, soll diese neue Optimierung es dem G1-Kollektor ermöglichen, diese wiederholten Zeichenfolgen im Heap zu identifizieren und sie auf dasselbe interne Zeichen zu verweisen []-Array, um mehrere Kopien derselben Zeichenfolge zu vermeiden, was die Heap-Nutzung ineffizient machen würde. Sie können den JVM-Parameter -XX:+UseStringDeduplication verwenden, um diese Funktion auszuprobieren. Java 8 und persistente GenerierungDie größte Änderung in Java 8 ist die Entfernung der persistenten Generierung, die ursprünglich zur Zuweisung von Speicherplatz für Klassenmetadaten, residente Zeichenfolgen und statische Variablen verwendet wurde . In der Vergangenheit erforderte dies von Entwicklern eine gezielte Optimierung und Anpassung des Heap-Verhältnisses für Anwendungen, die eine große Anzahl von Klassen laden würden. Dies gilt seit vielen Jahren und ist die Ursache für viele OutOfMemory-Ausnahmen. Daher ist es großartig, dass die JVM die Kontrolle übernimmt. Dennoch verringert es nicht automatisch die Möglichkeit, dass Entwickler Anwendungen in verschiedene JVMs entkoppeln.
Ihrer Anwendung den Durchsatz erhöhen oder verringern können.
Das obige ist der detaillierte Inhalt vonVergleichende Zusammenfassung verschiedener Java-Garbage Collectors. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!