Garbage Collection ist eine zentrale Funktion der Programmiersprache Java, die automatisch die Speicherzuweisung und -freigabe für Objekte verwaltet, die in einem Eden Space erstellt werden.
Mit Garbage Collection in Java können sich Entwickler auf das Schreiben von Code konzentrieren, ohne sich um die Speicherplatzverwaltung kümmern zu müssen. Das macht Java zu einer beliebten Wahl für die Entwicklung komplexer und umfangreicher Anwendungen. Für Java-Entwickler ist es jedoch wichtig zu verstehen, wie Garbage Collection funktioniert, um die Leistung ihres Codes zu optimieren und häufige speicherbezogene Fehler zu vermeiden.
Im Folgenden werden die Grundlagen der Garbage Collection in Java erkundet, einschließlich ihrer Vorteile, der verschiedenen Arten von Collectors und der Best Practices für die Codierung. Lesen Sie weiter und erfahren Sie, wie Garbage Collection funktioniert!
Dieser Fehler tritt auf, wenn ein Programm oder eine Anwendung versucht, mehr Arbeitsspeicher zu belegen als verfügbar ist. Das passiert, wenn die Java Virtual Machine (JVM) oder eine andere Plattform beim Versuch, eine Anwendung auszuführen, nicht über genügend Arbeitsspeicher verfügt.
Ein OutofMemoryError tritt typischerweise auf, wenn eine Anwendung oder ein Programm versucht, neue Objekte zu erstellen, die JVM aber nicht in der Lage ist, ihnen Speicherplatz zuzuweisen. Oder er tritt auf, wenn eine Anwendung zu viel Speicher verbraucht und diesen nicht ordnungsgemäß freigibt.
Wenn ein OutofMemoryError auftritt, stürzt die Anwendung normalerweise ab und wird beendet. Dieser Fehler tritt häufig bei Programmen auf, die mit großen Mengen an Metadaten arbeiten, z. B. bei Bild- oder Videoverarbeitungsprogrammen oder bei Programmen, die große Datenbanken verarbeiten.
Zur Beseitigung dieses Fehlers müssen Sie möglicherweise den für die Anwendung verfügbaren Speicher erhöhen oder die Speichernutzung der Anwendung optimieren. Das erreichen Sie, indem Sie den JVM-Parameter ändern oder einen Memory Profiler nutzen, um Speicherverluste oder ineffiziente Speicherauslastung zu identifizieren.
Alle Objekte werden in Java auf dem Heap gespeichert, einem Teil des Speichers, der für die dynamische Zuweisung von Objekten reserviert ist. Sobald ein Objekt nicht mehr von irgendeinem Teil des Programms verwendet wird, kommt es für die Garbage Collection infrage.
Der Garbage Collector in Java scannt regelmäßig den Heap-Speicher, um nicht verwendete Objekte zu finden. Der Prozess der Garbage Collection umfasst mehrere Schritte: Marking, Sweeping und Compacting.
Marking: Der erste Schritt der Garbage Collection umfasst das Markieren aller Objekte, auf die noch vom Programm verwiesen wird. Hierzu wird mit einer Reihe von Stammobjekten begonnen, z. B. globalen Variablen, lokalen Variablen und Methodenparametern, und dann werden alle Objekte verfolgt, die von diesen Stammobjekten aus erreicht werden können. Objekte, die nicht erreicht werden können, sind dann für die Garbage Collection geeignet.
Sweeping: Nach dem Marking sucht der Garbage Collector im Java-Heap nach den Objekten, die nicht mehr referenziert werden, und beansprucht den von ihnen verwendeten Speicher. Dabei wird der von den ungenutzten Objekten belegte Speicher freigegeben und dem freien Speicherpool wieder hinzugefügt.
Compacting: Bei manchen Garbage-Collection-Algorithmen folgt auf die Sweeping-Phase Compacting, in der der von den verbleibenden Objekten genutzte Speicher neu geordnet wird, um die Fragmentierung zu minimieren. Dazu müssen die Objekte näher aneinander liegen und größere zusammenhängende Blöcke freien Speichers geschaffen werden.
Die Java Virtual Machine (JVM) führt automatisch eine Garbage Collection durch, sodass der Programmierer den Speicher nicht manuell verwalten muss. Der Garbage Collector arbeitet in einem separaten Thread und wird normalerweise im Hintergrund ausgeführt, sodass das Programms weiter ausgeführt werden kann.
Es gibt zwei Haupttypen von Garbage Collection-Algorithmen in Java: Full Garbage Collection und Incremental Garbage Collection.
Bei der Full Garbage Collection durchsucht ein Garbage Collector (ein Teil des Laufzeitsystems einer Programmiersprache) den gesamten Speicher, der von einem Programm verwendet wird. Alle Objekte, die nicht mehr vom Programm verwendet werden kompiliert. Diese Objekte werden dann als Garbage markiert und können aus dem Speicher entfernt werden.
Die Full Garbage Collection wird in der Regel vom Laufzeitsystem einer Programmiersprache durchgeführt, die automatische Speicherverwaltung verwendet, wie z. B. Java oder Python. Während des Prozesses unterbricht der Garbage Collector für seine Suche die Programmausführung, was zu einer vorübergehenden Verlangsamung der Programmleistung führen kann.
Eine Full Garbage Collection wird üblicherweise ausgelöst, wenn der von einem Programm belegte Speicherplatz einen bestimmten Schwellenwert erreicht oder wenn das Programm einen neuen Speicherblock anfordert und nicht mehr genügend freier Speicher verfügbar ist. Das Ziel ist Speicher, der vom Programm nicht benötigt wird, wieder freizugeben, damit er von anderen Teilen des Programms oder von anderen Programmen, die auf demselben Rechner laufen, genutzt werden kann.
Bei der Incremental Garbage Collection handelt es sich um eine Speicherverwaltungstechnik, die von Programmiersprachen und Laufzeitumgebungen verwendet wird, um Speicher, der von einem Programm nicht mehr benötigt wird, automatisch zurückzugewinnen. Hierzu werden nicht verwendete Objekte im Speicher identifiziert und der von ihnen belegte Speicher wird freigegeben, damit er von anderen Teilen des Programms wiederverwendet werden kann.
Der Garbage Collector durchsucht den Speicher des Programms regelmäßig nach nicht erreichbaren Objekten im Heap-Speicher der jungen Generation. Anstatt die Ausführung des Programms während dieses Scanvorgangs anzuhalten, unterteilt der Garbage Collector den Scanvorgang in kleine, überschaubare Teile. Bei jeder Erhöhung durchsucht der Garbage Collector einen Teil des Programmspeichers, identifiziert alle Objekte, die nicht benötigt werden, und markiert sie als zur Wiederverwendung verfügbar.
Dadurch kann der Garbage Collector den Speicher in kleinen Teilen zurückfordern, ohne die Ausführung des Programms für längere Zeit zu unterbrechen. Dadurch wird sichergestellt, dass das Programm reaktionsschnell bleibt und keine erheblichen Pausen oder Verzögerungen entstehen.
Diese Art der Garbage Collection kann jedoch weniger effizient sein als andere, z. B. Mark-and-Sweep oder Generational Garbage Collection, da sie häufigere Scans des Programmspeichers erfordert. Darüber hinaus kann sie einen gewissen Overhead bei der Programmausführung verursachen, da der Garbage Collector zwischen den einzelnen Teilen Statusinformationen pflegen muss.
Die Garbage Collection von Java bietet insgesamt viele Vorteile, die sie zu einem wertvollen Werkzeug für Entwickler machen. Diese zum Beispiel:
Keine manuelle Speicherverwaltung: Mit Garbage Collection müssen Entwickler die Speicherzuweisung und -freigabe nicht manuell verwalten. So können sich Programmierer mehr auf das Schreiben von Code und weniger auf die Speicherverwaltung konzentrieren, was zur Reduzierung von Fehlern und zur Steigerung der Produktivität beitragen kann.
Weniger Speicherverluste: Garbage Collection hilft, Speicherverluste zu verhindern. Sie können auftreten, wenn ein Programm nicht mehr benötigten Speicher nicht freigibt. Dies kann dazu führen, dass das Programm mehr Speicher als nötig verbraucht, was zu einer langsamen Leistung und schließlich zum Absturz führt.
Dynamische Speicherzuordnung: Mit der Garbage Collection in Java ist eine dynamische Speicherzuweisung möglich, d. h. der Speicher wird bei Bedarf zur Laufzeit zugewiesen. Dadurch werden Fehler bei der Speicherzuweisung vermieden und das Programm kann effizienter werden.
Bessere Leistung: Die Garbage Collection kann die Leistung eines Programms steigern, indem der Zeitaufwand für die Speicherverwaltung reduziert wird. Das kann zu schnelleren Ausführungszeiten und einem reaktionsschnelleren Programm führen.
Speicheroptimierung: Mit der Garbage Collection kann die Speichernutzung optimiert werden, weil Speicher, der von einem Teil des Programms nicht genutzt wird, für andere Teile des Programms wiederverwendet wird. Dadurch kann die Speicherauslastung reduziert und die Gesamteffizienz des Programms verbessert werden.
Für Entwickler ergeben sich folgende Vorteile: automatische Speicherverwaltung, weniger Probleme beim Speichern, dynamische Speicherzuweisung, Leistungssteigerung und bessere Speichernutzung. Dazu unterstützt sie die Garbage Collection dabei, bessere und effizientere Programme zu schreiben.
In Java wird die Garbage Collection automatisch von der JVM (Java Virtual Machine) ausgelöst, wenn sie feststellt, dass der Heap-Speicher voll wird, oder nach einer gewissen Zeit.
Es gibt mehrere Ereignisse, die eine Garbage Collection in Java auslösen können:
Zuweisung von Heap-Speicherplatz: Sobald die JVM Speicher für ein neues Objekt zuweisen muss und nicht genügend Platz im Heap vorhanden ist, löst sie die Garbage Collection aus, um ungenutzten Speicher zurückzufordern oder im Survivor Space zu speichern.
System.gc()-Methodenaufruf: Damit kann die Garbage Collection explizit gestartet werden, aber nicht in jedem Fall.
Schwellenwert der Old Generation: Die Garbage Collection kann auch ausgelöst werden, wenn die Heap-Größe des Heap-Speicherplatzes der Old Generation (in dem alte Objekte gespeichert werden) einen bestimmten Schwellenwert erreicht.
PermGen/Metaspace Schwellenwert: In Java-Versionen vor Java 8 kann die Garbage Collection auch ausgelöst werden, wenn die Größe der Speicherbereiche PermGen (Permanent Generation) oder Metaspace (in Java 8 und höher) einen bestimmten Schwellenwert erreicht.
Zeitbasiert: Sie kann auch auf der Grundlage eines Zeitintervalls ausgelöst werden. Beispielsweise kann die JVM unabhängig von der Speichernutzung jede Stunde oder jeden Tag eine Garbage Collection auslösen.
Aber das tatsächliche Verhalten der Garbage Collection in Java kann je nach JVM-Implementierung und Konfiguration variieren.
So können Sie die Java Virtual Machine (JVM) auffordern, den Garbage Collector auszuführen:
Mit System.gc(): Mit dieser Methode wird die JVM aufgefordert, den Garbage Collector auszuführen. Es ist nicht garantiert, dass der Garbage Collector sofort nach dem Aufruf dieser Methode ausgeführt wird.
Mit -XX:+DisableExplicitGC: Dieses JVM-Flag deaktiviert explizite Garbage-Collection-Anfragen. Das bedeutet, dass selbst wenn Sie System.gc() oder Runtime.getRuntime().gc() verwenden, wird der Garbage Collector nicht ausgelöst.
Die explizite Aufforderung zur Ausführung des Garbage Collectors wird im Allgemeinen nicht empfohlen, da die JVM so konzipiert ist, dass sie die Speicherzuweisung und Garbage Collection automatisch verwaltet. Explizite Garbage Collection-Anforderungen können sich manchmal negativ auf die Leistung auswirken.
Sobald es von keinem Teil des Programms mehr referenziert wird. Die automatische Garbage Collection ist ein Prozess, der von der Laufzeitumgebung der Programmiersprache durchgeführt wird, um Speicher zurückzugewinnen.
In den meisten modernen Programmiersprachen wird die Garbage-Collection automatisch von der Laufzeitumgebung durchgeführt. Die für die Garbage Collection verwendeten Algorithmen können je nach Programmiersprache und Implementierung variieren, aber das Prinzip ist dasselbe: Die Laufzeitumgebung durchsucht regelmäßig den Heap (den Teil des Speichers, der für dynamisch zugewiesene Objekte verwendet wird), um Objekte zu identifizieren, die von keinem aktiven Objekt im Programm mehr erreicht werden können. Sobald erkannt wird, dass ein Objekt nicht erreichbar ist, wird es als Garbage markiert und der Speicher kann wieder verwendet werden.
Der Zeitpunkt, zu dem ein Objekt für die Garbage Collection qualifiziert ist, hängt von dem spezifischen Garbage Collection-Algorithmus ab, der von der Laufzeitumgebung verwendet wird. Einige Algorithmen sind offensiver als andere und geben den Speicher schneller frei, während andere die Garbage Collection verzögern, um die Leistung zu optimieren. Im Allgemeinen muss sich der Programmierer jedoch nicht um die manuelle Speicherverwaltung kümmern, da die Laufzeitumgebung dies automatisch übernimmt.
Einige Beispiele:
Serieller Garbage Collector: Der Serial Collector ist der standardmäßige Garbage Collector in Java und wird in der Regel in kleinen bis mittelgroßen Anwendungen mit wenig Datenfluss verwendet. Diese Art von Collector trägt dazu bei, dass die üblichen „Stop the World“-Ereignisse nicht auftreten.
Parallel Garbage Collector: Der Parallel Collector wurde für Anwendungen mit hohem Datenfluss entwickelt. Er ist besonders nützlich bei Anwendungen, die große Heaps erfordern, da er mehrere CPUs verwendet, um den Prozess zu beschleunigen. Wichtig ist, dass dieser Collector die Anwendungsthreads einfriert, wenn er ausgeführt wird.
Concurrent Mark Sweep (CMS) Collector: Der CMS-Collector wurde für Anwendungen entwickelt, die kurze Pausenzeiten erfordern, und ist nützlich für Anwendungen mit vielen aktiven Objekten.
G1 Garbage Collector: Der G1 Collector ist für große Heaps konzipiert und kann eine Mischung aus kurz- und langlebigen Objekten verarbeiten. Es verwendet mehrere Threads, um den Heap-Speicher gleichzeitig zu scannen und zu komprimieren.
Jeder Garbage Collector hat seine eigenen Stärken und Schwächen, und die Entscheidung, welcher Collector verwendet werden soll, hängt von den spezifischen Anforderungen der Anwendung ab. Die Einstellungen können auch konfiguriert und abgestimmt werden, um die Leistung für eine bestimmte Anwendung zu optimieren.
Garbage Collection und Speicherlecks haben etwas mit der Speicherverwaltung in Computerprogrammen zu tun, aber mit unterschiedlichen Bedeutungen und Implikationen.
Wie oben beschrieben, wird die Garbage Collection in der Regel von der Programmiersprache oder der Laufzeitumgebung durchgeführt und trägt dazu bei, dass Programme nicht mehr Speicher verbrauchen, als sie benötigen. Sie identifiziert Speicher, der von anderen Teilen des Programms oder von anderen Programmen, die auf dem Computer laufen, genutzt werden kann.
Im Gegensatz dazu tritt ein Speicherleck auf, wenn ein Programm den zugewiesenen Speicher nicht freigibt, selbst wenn dieser Speicher nicht mehr benötigt wird. Dadurch verbraucht das Programm im Laufe der Zeit immer mehr Speicher. Schließlich ist der verfügbare Speicher erschöpft, was zum Absturz des Programms oder des gesamten Betriebssystems führen kann. Speicherlecks werden in der Regel durch Programmfehler verursacht, und es kann schwierig sein, sie zu identifizieren und zu beheben.
Bei der Garbage Collection handelt es sich also um einen Prozess zur automatischen Freigabe von Speicher, der nicht mehr benötigt wird. Speicherlecks treten auf, wenn von einem Programm Speicher zugewiesen und nicht wieder freigegeben wird. Dadurch kommt es zu einem allmählichen Anstieg der Speichernutzung.
Die Garbage Collection ist ein wesentlicher Aspekt der Java-Programmierung, der eine effiziente Speicherverwaltung durch Rückgewinnung von ungenutztem Speicher gewährleistet. Instana Observability bietet Entwicklern leistungsstarke Tools, um den Prozess der Garbage Collection in Echtzeit zu überwachen und zu optimieren.
Mit Instana können Entwickler Speicherlecks schnell identifizieren, die Einstellungen für die Garbage Collection optimieren und etwaige Leistungsprobleme beheben.
Dank der umfassenden Überwachungsfunktionen von Instana erhalten Entwickler detaillierte Erkenntnisse in die Speichernutzung und Garbage Collection ihrer Java-Anwendungen und können so leistungsstarke und zuverlässige Software bereitstellen.
Mithilfe der in diesem Leitfaden beschriebenen Best Practices können Entwickler mit Instana den Garbage Collection-Prozess optimieren und die Gesamtleistung ihrer Java-Anwendungen verbessern. Dank der Instana Observability haben Entwickler die Möglichkeit, allen auftretenden Problemen zuvorzukommen und sicherzustellen, dass ihre Anwendungen stets die bestmögliche Leistung erbringen.
Steigern Sie die Funktionalität und die Observability in Ihrem Unternehmens-APM, verbessern Sie das Application Performance Management und beschleunigen Sie CI/CD-Pipelines, unabhängig davon, wo sich die Anwendungen befinden.