it-swarm-eu.dev

Wann macht System.gc () etwas?

Ich weiß, dass die Garbage Collection in Java automatisiert ist. Ich habe jedoch verstanden, dass die JVM, wenn Sie in Ihrem Code System.gc() aufrufen, möglicherweise entscheidet, an diesem Punkt eine Garbage Collection durchzuführen. Wie funktioniert das genau? Auf welcher Grundlage/mit welchen Parametern entscheidet die JVM, einen GC durchzuführen (oder nicht), wenn sie System.gc() sieht?

Gibt es Beispiele, in welchen Fällen es eine gute Idee ist, dies in Ihren Code einzufügen?

111
harry

In der Praxis wird normalerweise entschieden, eine Speicherbereinigung durchzuführen. Die Antwort hängt von vielen Faktoren ab, z. B. davon, auf welcher JVM Sie ausgeführt werden, in welchem ​​Modus sie sich befindet und welchen Garbage Collection-Algorithmus sie verwendet.

Ich würde mich in Ihrem Code nicht darauf verlassen. Wenn die JVM im Begriff ist, einen OutOfMemoryError auszulösen, wird er durch Aufrufen von System.gc () nicht gestoppt, da der Garbage Collector versucht, so viel wie möglich freizugeben, bevor er so extrem wird. Ich habe es in der Praxis nur in IDEs gesehen, in denen es an eine Schaltfläche angehängt ist, auf die ein Benutzer klicken kann, aber selbst dort ist es nicht besonders nützlich.

58
jodonnell

Das einzige Beispiel, an das ich denken kann, wo es Sinn macht, System.gc () aufzurufen, ist das Profilieren einer Anwendung, um nach möglichen Speicherverlusten zu suchen. Ich glaube, die Profiler rufen diese Methode kurz vor dem Erstellen eines Speicherabbilds auf.

29

Die Java Sprachspezifikation garantiert nicht, dass die JVM einen GC startet, wenn Sie System.gc() aufrufen. Dies ist der Grund, warum "sich möglicherweise für einen GC entschieden hat oder nicht an diesem Punkt".

Wenn Sie sich nun OpenJDK-Quellcode ansehen, das das Rückgrat von Oracle JVM ist, werden Sie feststellen, dass ein Aufruf von System.gc() einen GC-Zyklus startet. Wenn Sie eine andere JVM wie J9 verwenden, müssen Sie deren Dokumentation überprüfen, um die Antwort herauszufinden. Die JVM von Azul verfügt beispielsweise über einen Garbage Collector, der kontinuierlich ausgeführt wird, sodass ein Aufruf von System.gc() nichts bewirkt

Einige andere Antworten erwähnen das Starten eines GC in JConsole oder VisualVM. Grundsätzlich rufen diese Tools System.gc() per Fernzugriff auf.

Normalerweise möchten Sie einen Garbage Collection-Zyklus nicht von Ihrem Code aus starten, da er die Semantik Ihrer Anwendung durcheinanderbringt. Ihre Anwendung erledigt einige geschäftliche Aufgaben, die JVM kümmert sich um die Speicherverwaltung. Sie sollten diese Bedenken voneinander trennen (lassen Sie Ihre Anwendung kein Speichermanagement durchführen, sondern konzentrieren Sie sich auf das Geschäft).

Es gibt jedoch nur wenige Fälle, in denen ein Aufruf von System.gc() verständlich sein kann. Betrachten Sie zum Beispiel Mikrobenchmarks. Niemand möchte, dass ein GC-Zyklus mitten in einem Mikrobenchmark stattfindet. Sie können also zwischen jeder Messung einen GC-Zyklus auslösen, um sicherzustellen, dass jede Messung mit einem leeren Haufen beginnt.

24
Pierre Laporte

Sie haben keine Kontrolle über GC in Java - der VM entscheidet. Ich bin noch nie auf einen Fall gestoßen, in dem System.gc() ist benötigt . Da ein System.gc() Aufruf einfach EMPFIEHLT, dass der VM eine Garbage Collection macht und es auch Wenn eine vollständige Speicherbereinigung durchgeführt wird (alte und neue Generationen in einem Heap mit mehreren Generationen), kann dies tatsächlich dazu führen, dass MEHR CPU-Zyklen als erforderlich verbraucht werden.

In einigen Fällen kann es sinnvoll sein, VM JETZT eine vollständige Erfassung vorzuschlagen, da Sie möglicherweise wissen, dass die Anwendung die nächsten Minuten im Leerlauf bleibt, bevor schweres Heben auftritt Beispiel: Direkt nach der Initialisierung vieler temporärer Objekte während des Startvorgangs der Anwendung (dh ich habe gerade eine TON von Informationen zwischengespeichert, und ich weiß, dass ich ungefähr eine Minute lang nicht viel Aktivität bekomme.) Denken Sie an ein IDE wie das Starten von Eclipse - es ist viel zu tun, um es zu initialisieren, also ist es vielleicht unmittelbar nach der Initialisierung sinnvoll, an diesem Punkt eine vollständige GC durchzuführen.

23
DustinB

Sie müssen sehr vorsichtig sein, wenn Sie System.gc() aufrufen. Wenn Sie es aufrufen, kann dies zu unnötigen Leistungsproblemen in Ihrer Anwendung führen, und es kann nicht garantiert werden, dass tatsächlich eine Erfassung durchgeführt wird. Es ist tatsächlich möglich, explizite System.gc() über das Java argument -XX:+DisableExplicitGC Zu deaktivieren.

Ich würde wärmstens empfehlen, die Dokumente zu lesen, die unter Java HotSpot Garbage Collection verfügbar sind, um detailliertere Informationen zur Garbage Collection zu erhalten.

17

System.gc() wird von der VM implementiert und ist implementierungsspezifisch. Der Implementierer könnte zum Beispiel einfach zurückkehren und nichts tun.

Wenn Sie eine manuelle Sammlung erstellen möchten, können Sie dies nur dann tun, wenn Sie eine große Sammlung mit vielen kleineren Sammlungen aufgeben - a Map<String,<LinkedList>> zum Beispiel - und Sie möchten versuchen, ab und zu den Perf-Hit zu machen, aber zum größten Teil sollten Sie sich darüber keine Sorgen machen. Der GC weiß es leider die meiste Zeit besser als Sie.

10
Patrick

Wenn Sie Direktspeicherpuffer verwenden, führt die JVM den GC nicht für Sie aus, selbst wenn Ihnen der Direktspeicher ausgeht.

Wenn Sie ByteBuffer.allocateDirect() aufrufen und einen OutOfMemoryError erhalten, können Sie feststellen, dass dieser Aufruf in Ordnung ist, nachdem Sie einen GC manuell ausgelöst haben.

8
Peter Lawrey

Die meisten JVMs starten einen GC (abhängig von der Option -XX: DiableExplicitGC und -XX: + ExplicitGCInvokesConcurrent). Die Spezifikation ist jedoch weniger genau definiert, um später eine bessere Implementierung zu ermöglichen.

Die Spezifikation muss geklärt werden: Bug # 6668279: (spec) System.gc () sollte darauf hinweisen, dass wir die Verwendung nicht empfehlen und das Verhalten nicht garantieren

Intern wird die gc-Methode von RMI und NIO verwendet und erfordert eine synchrone Ausführung. Dies wird derzeit diskutiert:

Bug # 5025281: Erlaube System.gc (), gleichzeitige (nicht weltweite) vollständige Sammlungen auszulösen

5
eckes

Garbage Collection Ist in Java gut, wenn wir Software ausführen, die in Java in Desktop/Laptop/Server codiert ist. Sie können System.gc() aufrufen. oder Runtime.getRuntime().gc() in Java.

Beachten Sie nur, dass keiner dieser Anrufe garantiert etwas bewirkt. Sie sind nur ein Vorschlag für den JVM, den Garbage Collector auszuführen. Es liegt an der JVM, ob sie den GC ausführt oder nicht. Also, kurze Antwort: Wir wissen nicht, wann es läuft. Längere Antwort: JVM würde gc ausführen, wenn es dafür Zeit hat.

Ich glaube, das gilt auch für Android. Dies kann jedoch Ihr System verlangsamen.

2
Naveen

Normalerweise würde VM vor dem Auslösen einer OutOfMemoryException automatisch eine Garbage Collection durchführen, sodass das Hinzufügen eines expliziten Aufrufs nicht hilfreich sein sollte, es sei denn, der Performance-Hit wird möglicherweise zu einem früheren Zeitpunkt verschoben.

Ich glaube jedoch, dass ich auf einen Fall gestoßen bin, in dem dies relevant sein könnte. Ich bin mir jedoch nicht sicher, da ich noch testen muss, ob es irgendwelche Auswirkungen hat:

Wenn Sie eine Datei im Speicher zuordnen, löst der Aufruf von map () meiner Meinung nach eine IOException aus, wenn ein ausreichend großer Speicherblock nicht verfügbar ist. Eine Garbage Collection kurz vor der map () -Datei könnte das verhindern, denke ich. Was denkst du?

2
Vashek

wir können niemals Müllabfuhr erzwingen. System.gc schlägt nur vm für die Garbage Collection vor, jedoch weiß niemand genau, wann der Mechanismus ausgeführt wird. Dies wird in den JSR-Spezifikationen angegeben.

2
lwpro2

Es gibt eine Menge zu sagen, wenn man sich die Zeit nimmt, die verschiedenen Einstellungen für die Speicherbereinigung zu testen, aber wie oben erwähnt, ist es normalerweise nicht sinnvoll, dies zu tun.

Ich arbeite derzeit an einem Projekt mit einer speicherbeschränkten Umgebung und einer relativ großen Datenmenge. Es gibt einige große Datenmengen, die meine Umgebung an ihre Grenzen bringen, obwohl ich die Speichernutzung reduzieren konnte Theoretisch sollte es gut funktionieren, ich würde immer noch Heap-Space-Fehler bekommen. Die ausführlichen GC-Optionen zeigten mir, dass versucht wurde, Müll zu sammeln, aber ohne Erfolg. Im Debugger konnte ich System.gc () ausführen und sicher genug, dass "viel" Speicher verfügbar wäre ... nicht viel mehr, aber genug.

Infolgedessen ruft meine Anwendung System.gc () nur dann auf, wenn gerade das Codesegment eingegeben wird, in dem große, für die Verarbeitung der Daten erforderliche Puffer zugewiesen werden, und ein Test des verfügbaren freien Speichers zeigt an, dass dies nicht der Fall ist garantiert haben. Insbesondere schaue ich auf eine 1 GB-Umgebung, in der mindestens 300 MB statische Daten enthalten, wobei der Großteil der nicht statischen Daten ausführungsbezogen ist, es sei denn, die verarbeiteten Daten haben zufällig eine Größe von mindestens 100 bis 200 MB die Quelle. Dies ist alles Teil eines automatischen Datenkonvertierungsprozesses, sodass die Daten auf lange Sicht nur für relativ kurze Zeiträume vorhanden sind.

Obwohl Informationen zu den verschiedenen Optionen für die Optimierung des Garbage Collectors verfügbar sind, scheint dies ein weitgehend experimenteller Prozess zu sein, und es ist nicht einfach, Informationen zu erhalten, die zum Verständnis des Umgangs mit diesen speziellen Situationen erforderlich sind.

Obwohl ich System.gc () verwende, habe ich die Optimierung mithilfe von Befehlszeilenparametern fortgesetzt und es geschafft, die Gesamtverarbeitungszeit meiner Anwendung um einen relativ signifikanten Betrag zu verbessern, obwohl ich nicht in der Lage war, über das Problem hinwegzukommen Stolperstein beim Arbeiten mit den größeren Datenblöcken. Abgesehen davon ist System.gc () ein Werkzeug ... ein sehr unzuverlässiges Werkzeug, und wenn Sie nicht vorsichtig sind, wie Sie es verwenden, werden Sie sich wünschen, dass es nicht öfter funktioniert als nicht.

2
Kyune

Zusamenfassend:

Parameter sind VM abhängig.

Beispielverwendung - für Laufzeit-/Produktions-Apps fällt keine ein, aber es ist nützlich, sie für einige Profilerstellungskonzepte auszuführen, z. B. für Anrufe

// test run #1
test();
for (int i=0; i<10; i++) { 
// calling repeatedly to increase chances of a clean-up
  System.gc(); 
}
// test run #2
test();
1
mataal

Wenn Sie wissen möchten, ob Ihre System.gc() aufgerufen wird, können Sie mit dem neuen Java 7 update 4 eine Benachrichtigung erhalten, wenn die JVM die Garbage Collection durchführt.

Ich bin mir nicht 100% sicher, ob die Klasse GarbageCollectorMXBean in Java= 7 Update 4 eingeführt wurde, da ich sie in den Versionshinweisen nicht finden konnte, aber gefunden habe die Informationen in der javaperformancetuning . com-Site

1
Shervin Asgari

Nach Thinking in Java von Bruce Eckel ist ein Anwendungsfall für den expliziten System.gc () -Aufruf, wenn Sie die Finalisierung erzwingen möchten, im Aufruf an - finalize Methode.

0
Asterisk

Ich kann mir kein konkretes Beispiel vorstellen, wenn es gut ist, explizite GCs auszuführen.

Im Allgemeinen kann das Ausführen einer expliziten GC mehr Schaden als Nutzen verursachen, da eine explizite GC eine vollständige Auflistung auslöst, die bei jedem Objekt erheblich länger dauert. Wenn dieser explizite GC wiederholt aufgerufen wird, kann dies leicht zu einer langsamen Anwendung führen, da viel Zeit für die Ausführung vollständiger GCs aufgewendet wird.

Wenn Sie den Heap mit einem Heap-Analysator durchsuchen und vermuten, dass eine Bibliothekskomponente explizite GCs aufruft, können Sie Folgendes deaktivieren: gc = -XX: + DisableExplicitGC zu den JVM-Parametern hinzufügen.

0
zxcv

während system.gc funktioniert, stoppt es die Welt: Alle Antworten werden gestoppt, sodass der Garbage Collector jedes Objekt scannen kann, um zu prüfen, ob es gelöscht werden muss. Wenn es sich bei der Anwendung um ein Webprojekt handelt, werden alle Anforderungen gestoppt, bis gc beendet ist. Dies führt dazu, dass Ihr Webprojekt nicht in einem Monent ausgeführt werden kann.

0
fleture