Nachdem ich eine Frage zum Erzwingen von Objekten in Java (der Typ löschte eine 1,5-GB-HashMap) mit beantwortet hatteSystem.gc()
, wurde mir gesagt, dass es eine schlechte Praxis sei, System.gc()
manuell aufzurufen , aber die Kommentare waren nicht ganz überzeugend. Außerdem schien es niemand zu wagen, meine Antwort zu stimmen oder zu stimmen.
Dort wurde mir gesagt, dass es eine schlechte Praxis ist, aber dann wurde mir auch gesagt, dass Garbage Collector-Läufe die Welt nicht mehr systematisch stoppen und dass sie auch von der JVM effektiv nur als Hinweis verwendet werden könnten, also bin ich irgendwie Bei Verlust.
Ich verstehe, dass die JVM normalerweise besser als Sie weiß, wann sie Speicher zurückfordern muss. Ich verstehe auch, dass es dumm ist, sich um ein paar Kilobyte Daten zu sorgen. Ich verstehe auch, dass selbst Megabyte an Daten nicht mehr so sind wie vor ein paar Jahren. Aber immer noch 1,5 Gigabyte? Und Sie wissen, dass etwa 1,5 GB Daten im Speicher herumhängen. Es ist nicht so, als wäre es ein Schuss in die Dunkelheit. Ist System.gc()
systematisch schlecht oder gibt es einen Punkt, an dem es in Ordnung wird?
Die Frage ist also eigentlich doppelt:
- Warum ist oder ist es nicht schlecht anzurufen
System.gc()
? Ist es unter bestimmten Implementierungen wirklich nur ein Hinweis auf die JVM oder handelt es sich immer um einen vollständigen Erfassungszyklus? Gibt es wirklich Garbage Collector-Implementierungen, die ihre Arbeit erledigen können, ohne die Welt zu stoppen? Bitte werfen Sie ein Licht auf die verschiedenen Behauptungen, die in den Kommentaren zu meiner Antwort gemacht wurden . - Wo ist die Schwelle? Ist es nie eine gute Idee anzurufen
System.gc()
oder gibt es Zeiten, in denen es akzeptabel ist? Wenn ja, wie sind diese Zeiten?
quelle
Antworten:
Der Grund, den jeder immer zu vermeiden sagt,
System.gc()
ist, dass es ein ziemlich guter Indikator für grundlegend kaputten Code ist . Jeder Code, dessen Richtigkeit davon abhängt, ist mit Sicherheit fehlerhaft. Alle, die sich für die Leistung darauf verlassen, sind höchstwahrscheinlich defekt.Sie wissen nicht, unter welcher Art von Müllsammler Sie laufen. Es gibt sicherlich einige, die die Welt nicht "aufhalten", wie Sie behaupten, aber einige JVMs sind nicht so schlau oder tun es aus verschiedenen Gründen (vielleicht telefonieren sie?) Nicht. Sie wissen nicht, was es tun wird.
Es ist auch nicht garantiert, dass etwas getan wird. Die JVM ignoriert Ihre Anfrage möglicherweise vollständig.
Die Kombination aus "Sie wissen nicht, was es tun wird", "Sie wissen nicht, ob es überhaupt helfen wird" und "Sie sollten es sowieso nicht nennen müssen" sind der Grund, warum die Leute dies im Allgemeinen so eindringlich sagen du solltest es nicht nennen. Ich denke, es ist ein Fall von "Wenn Sie fragen müssen, ob Sie dies verwenden sollten, sollten Sie nicht"
BEARBEITEN , um einige Bedenken aus dem anderen Thread auszuräumen:
Nachdem Sie den von Ihnen verlinkten Thread gelesen haben, möchte ich noch auf einige weitere Dinge hinweisen. Zunächst schlug jemand vor, dass der Aufruf
gc()
möglicherweise Speicher an das System zurückgibt. Das ist sicherlich nicht unbedingt wahr - der Java-Heap selbst wächst unabhängig von Java-Zuweisungen.Wie in speichert die JVM Speicher (viele zehn Megabyte) und vergrößert den Heap nach Bedarf. Dieser Speicher wird nicht unbedingt an das System zurückgegeben, selbst wenn Sie Java-Objekte freigeben. Es ist völlig kostenlos, den zugewiesenen Speicher für zukünftige Java-Zuweisungen beizubehalten.
Um zu zeigen, dass es möglich ist, dass
System.gc()
nichts funktioniert, sehen Sie:http://bugs.sun.com/view_bug.do?bug_id=6668279
und insbesondere, dass es eine VM-Option -XX: DisableExplicitGC gibt .
quelle
System.gc()
nützlich und möglicherweise sogar notwendig ist. Beispielsweise kann es in UI-Anwendungen unter Windows den Wiederherstellungsprozess eines Fensters erheblich beschleunigen, wenn Sie System.gc () aufrufen, bevor Sie das Fenster minimieren (insbesondere, wenn es für einige Zeit minimiert bleibt und Teile des Prozesses ausgetauscht werden Platte).WeakReference
s für Objekte verwendet, an denen Sie festhalten möchten, von Anfang an falsch ist, ob Speicherbereinigung oder nicht. Sie hätten das gleiche Problem in C ++ mitstd::weak_ptr
(obwohl Sie das Problem in einer C ++ - Version möglicherweise früher als in einer Java-Version bemerken würden, da die Objektzerstörung nicht wie normalerweise bei der Finalisierung zurückgestellt würde).System.gc()
behoben wird, ist eine Problemumgehung und keine gute Codierungspraxis.Es wurde bereits erklärt, dass das Aufrufen
system.gc()
möglicherweise nichts bewirkt und dass jeder Code, der den Garbage Collector zum Ausführen "benötigt", fehlerhaft ist.Der pragmatische Grund, warum es eine schlechte Praxis ist, anzurufen,
System.gc()
ist jedoch, dass es ineffizient ist. Und im schlimmsten Fall ist es schrecklich ineffizient ! Lassen Sie mich erklären.Ein typischer GC-Algorithmus identifiziert Müll, indem er alle Nicht-Müll-Objekte im Heap durchläuft und daraus schließt, dass jedes nicht besuchte Objekt Müll sein muss. Daraus können wir die Gesamtarbeit einer Garbage Collection modellieren, die aus einem Teil besteht, der proportional zur Menge der Live-Daten ist, und einem anderen Teil, der proportional zur Menge des Garbage ist. dh
work = (live * W1 + garbage * W2)
.Angenommen, Sie führen in einer Anwendung mit einem Thread Folgendes aus.
Der erste Anruf wird (wir sagen voraus)
(live * W1 + garbage * W2)
funktionieren und den ausstehenden Müll loswerden.Der zweite Anruf
(live* W1 + 0 * W2)
funktioniert und fordert nichts zurück. Mit anderen Worten, wir haben(live * W1)
Arbeit geleistet und absolut nichts erreicht .Wir können die Effizienz des Sammlers als den Arbeitsaufwand modellieren, der zum Sammeln einer Mülleinheit erforderlich ist. dh
efficiency = (live * W1 + garbage * W2) / garbage
. Um den GC so effizient wie möglich zu gestalten, müssen wir den Wert maximieren,garbage
wenn wir den GC ausführen. dh warten, bis der Haufen voll ist. (Und machen Sie den Haufen so groß wie möglich. Aber das ist ein separates Thema.)Wenn die Anwendung nicht stört (durch Aufrufen
System.gc()
), wartet der GC, bis der Heap voll ist, bevor er ausgeführt wird, was zu einer effizienten Sammlung von Garbage 1 führt . Wenn die Anwendung den GC jedoch zur Ausführung zwingt, ist der Heap wahrscheinlich nicht voll, und das Ergebnis ist, dass der Müll ineffizient gesammelt wird. Und je öfter die Anwendung die GC erzwingt, desto ineffizienter wird die GC.Hinweis: Die obige Erklärung beschönigt die Tatsache, dass ein typischer moderner GC den Heap in "Leerzeichen" unterteilt, der GC den Heap dynamisch erweitern kann, die Arbeitsgruppe der Nicht-Garbage-Objekte der Anwendung variieren kann und so weiter. Trotzdem gilt auf allen Ebenen das gleiche Grundprinzip für alle echten Müllsammler 2 . Es ist ineffizient, den GC zum Ausführen zu zwingen.
1 - So funktioniert der "Durchsatz" -Kollektor. Gleichzeitige Kollektoren wie CMS und G1 verwenden unterschiedliche Kriterien, um zu entscheiden, wann der Garbage Collector gestartet werden soll.
2 - Ich schließe auch Speichermanager aus, die ausschließlich Referenzzählung verwenden, aber keine aktuelle Java-Implementierung verwendet diesen Ansatz ... aus gutem Grund.
quelle
Viele Leute scheinen dir zu sagen, dass du das nicht tun sollst. Ich stimme dir nicht zu. Wenn Sie nach einem großen Ladevorgang wie dem Laden eines Levels glauben, dass:
Das Aufrufen von System.gc () kann nicht schaden. Ich sehe es wie das
inline
Schlüsselwort c / c ++ . Es ist nur ein Hinweis für den GC, dass Sie als Entwickler entschieden haben, dass Zeit / Leistung nicht so wichtig ist wie gewöhnlich und dass ein Teil davon verwendet werden könnte, um Speicher zurückzugewinnen.Der Rat, sich nicht darauf zu verlassen, dass etwas getan wird, ist richtig. Verlassen Sie sich nicht darauf, dass es funktioniert, aber es ist vollkommen in Ordnung, den Hinweis zu geben, dass jetzt ein akzeptabler Zeitpunkt zum Sammeln ist. Ich würde lieber Zeit an einem Punkt im Code verschwenden, an dem es keine Rolle spielt (Ladebildschirm), als wenn der Benutzer aktiv mit dem Programm interagiert (wie während eines Levels eines Spiels).
Es gibt eine Zeit, in der ich die Erfassung erzwingen werde : Wenn ich versuche herauszufinden, ob ein bestimmtes Objekt leckt (entweder nativer Code oder große, komplexe Rückrufinteraktion. Oh, und jede UI-Komponente, die Matlab auch nur ansieht). Dies sollte niemals verwendet werden im Produktionscode.
quelle
stop the world
Ansatz erfordern , und dies ist ein echter Schaden, wenn es passiertDie Leute haben gute Arbeit geleistet und erklärt, warum sie NICHT verwenden sollten. Deshalb werde ich Ihnen einige Situationen erläutern, in denen Sie sie verwenden sollten:
(Die folgenden Kommentare gelten für Hotspot, der unter Linux mit dem CMS-Collector ausgeführt wird. Ich bin zuversichtlich, dass
System.gc()
dies tatsächlich immer eine vollständige Garbage Collection aufruft.)Nach der ersten Arbeit beim Starten Ihrer Anwendung kann es zu einer schrecklichen Speichernutzung kommen. Die Hälfte Ihrer festen Generation könnte voller Müll sein, was bedeutet, dass Sie Ihrem ersten CMS so viel näher sind. In Anwendungen, in denen dies wichtig ist, ist es keine schlechte Idee, System.gc () aufzurufen, um Ihren Heap auf den Startzustand von Live-Daten zurückzusetzen.
Wenn Sie Ihre Heap-Nutzung genau überwachen, möchten Sie genau wie # 1 genau wissen, wie hoch Ihre Basisspeicherauslastung ist. Wenn die ersten 2 Minuten der Betriebszeit Ihrer Anwendung vollständig initialisiert sind, werden Ihre Daten durcheinander gebracht, es sei denn, Sie erzwingen (ähm ... "vorschlagen") die volle gc im Voraus.
Möglicherweise haben Sie eine Anwendung, die so konzipiert ist, dass sie während der Ausführung niemals etwas für die fest angestellte Generation heraufbeschwört. Aber vielleicht müssen Sie einige Daten im Voraus initialisieren, die nicht so groß sind, dass sie automatisch zur dauerhaften Generation verschoben werden. Wenn Sie System.gc () nicht aufrufen, nachdem alles eingerichtet wurde, können Ihre Daten in der neuen Generation gespeichert werden, bis die Zeit für die Heraufstufung gekommen ist. Plötzlich wird Ihre Super-Duper-Anwendung mit geringer Latenz und niedrigem GC mit einer RIESIGEN (natürlich relativ) Latenzstrafe belegt, wenn Sie diese Objekte während des normalen Betriebs bewerben.
Manchmal ist es nützlich, einen System.gc-Aufruf in einer Produktionsanwendung verfügbar zu haben, um das Vorhandensein eines Speicherverlusts zu überprüfen. Wenn Sie wissen, dass der Satz von Live-Daten zum Zeitpunkt X in einem bestimmten Verhältnis zum Satz von Live-Daten zum Zeitpunkt Y vorhanden sein sollte, kann es hilfreich sein, System.gc () zum Zeitpunkt X und zum Zeitpunkt Y aufzurufen und die Speichernutzung zu vergleichen .
quelle
System.gc()
einmal anrufen , um die Förderung von Objekten zu erzwingen, erhalten Sie nichts. Und Sie möchten sicherlich nichtSystem.gc()
acht Mal hintereinander anrufen und beten, dass die Aktion jetzt abgeschlossen ist und die gesparten Kosten einer späteren Aktion die Kosten mehrerer vollständiger GCs rechtfertigen. Abhängig vom GC-Algorithmus trägt das Bewerben vieler Objekte möglicherweise nicht einmal die tatsächlichen Kosten, da nur der Speicher der alten Generation zugewiesen oder gleichzeitig kopiert wird…Dies ist eine sehr lästige Frage, und ich glaube, dass viele dazu beitragen, dass sich Java gegen Java ausspricht, obwohl es für eine Sprache nützlich ist.
Die Tatsache, dass Sie "System.gc" nicht vertrauen können, um etwas zu tun, ist unglaublich entmutigend und kann leicht das Gefühl "Angst, Unsicherheit, Zweifel" für die Sprache hervorrufen.
In vielen Fällen ist es hilfreich, mit Speicherspitzen umzugehen, die Sie absichtlich verursachen, bevor ein wichtiges Ereignis eintritt. Dies würde dazu führen, dass Benutzer glauben, Ihr Programm sei schlecht gestaltet / reagiert nicht.
Die Fähigkeit, die Speicherbereinigung zu steuern, wäre ein großartiges Schulungsinstrument, um das Verständnis der Menschen für die Funktionsweise der Speicherbereinigung zu verbessern und Programme dazu zu bringen, das Standardverhalten sowie das kontrollierte Verhalten auszunutzen.
Lassen Sie mich die Argumente dieses Threads überprüfen.
Oft macht das Programm nichts und Sie wissen, dass es aufgrund der Art und Weise, wie es entworfen wurde, nichts tut. Zum Beispiel kann es sein, dass es eine lange Wartezeit mit einem großen Wartemeldungsfeld gibt, und am Ende kann es auch einen Aufruf zum Sammeln von Müll hinzufügen, da die Zeit zum Ausführen einen sehr kleinen Bruchteil der Zeit in Anspruch nimmt langes Warten, aber verhindert, dass gc mitten in einer wichtigeren Operation agiert.
Ich bin anderer Meinung, es spielt keine Rolle, welchen Müllsammler Sie haben. Seine Aufgabe ist es, Müll aufzuspüren und zu reinigen.
Indem Sie den gc in Zeiten aufrufen, in denen die Nutzung weniger kritisch ist, verringern Sie die Wahrscheinlichkeit, dass er ausgeführt wird, wenn Ihr Leben von dem spezifischen Code abhängt, der ausgeführt wird. Stattdessen wird entschieden, Müll zu sammeln.
Sicher, es verhält sich möglicherweise nicht so, wie Sie es möchten oder erwarten, aber wenn Sie es aufrufen möchten, wissen Sie, dass nichts passiert, und der Benutzer ist bereit, Langsamkeit / Ausfallzeiten zu tolerieren. Wenn das System.gc funktioniert, großartig! Wenn nicht, haben Sie es zumindest versucht. Es gibt einfach keine Nachteile, es sei denn, der Garbage Collector hat inhärente Nebenwirkungen, die etwas schrecklich Unerwartetes bewirken, wie sich ein Garbage Collector verhalten soll, wenn er manuell aufgerufen wird, und dies allein verursacht Misstrauen.
Dies ist ein Anwendungsfall, der nicht zuverlässig erreicht werden kann, aber möglicherweise, wenn das System so konzipiert wurde. Es ist so, als würde man eine Ampel erstellen und so gestalten, dass einige / alle Ampeltasten nichts tun. Man fragt sich, warum die Taste zunächst vorhanden ist. Javascript hat keine Speicherbereinigungsfunktion, also ziehen wir an prüfe es nicht so sehr dafür.
Was ist ein "Hinweis"? Was ist "ignorieren"? Ein Computer kann nicht einfach Hinweise nehmen oder etwas ignorieren. Es gibt strenge Verhaltenspfade, die dynamisch sein können und von der Absicht des Systems geleitet werden. Eine richtige Antwort würde beinhalten, was der Garbage Collector auf Implementierungsebene tatsächlich tut, was dazu führt, dass er keine Erfassung durchführt, wenn Sie ihn anfordern. Ist die Funktion einfach ein Nein? Gibt es irgendwelche Bedingungen, die ich erfüllen muss? Was sind diese Bedingungen?
So wie es aussieht, scheint Javas GC oft ein Monster zu sein, dem man einfach nicht vertraut. Sie wissen nicht, wann es kommen oder gehen wird, Sie wissen nicht, was es tun wird, wie es es tun wird. Ich kann mir vorstellen, dass einige Experten eine bessere Vorstellung davon haben, wie ihre Garbage Collection pro Anweisung funktioniert, aber die große Mehrheit hofft einfach, dass sie "nur funktioniert", und es ist frustrierend, einem undurchsichtig wirkenden Algorithmus vertrauen zu müssen, um für Sie zu arbeiten.
Es gibt eine große Lücke zwischen dem Lesen über etwas oder dem Unterrichten von etwas und dem tatsächlichen Erkennen der Implementierung, der Unterschiede zwischen den Systemen und der Möglichkeit, damit zu spielen, ohne sich den Quellcode ansehen zu müssen. Dies schafft Vertrauen und ein Gefühl der Meisterschaft / des Verständnisses / der Kontrolle.
Zusammenfassend gibt es ein inhärentes Problem mit den Antworten: "Diese Funktion kann möglicherweise nichts bewirken, und ich werde nicht näher darauf eingehen, wie zu erkennen ist, wann sie etwas tut und wann nicht und warum sie nicht oder wird." oft impliziert dies, dass es einfach gegen die Philosophie verstößt, dies zu versuchen, auch wenn die Absicht dahinter vernünftig ist ".
Es mag für Java GC in Ordnung sein, sich so zu verhalten, wie es ist, oder auch nicht, aber um es zu verstehen, ist es schwierig, wirklich zu verfolgen, in welche Richtung Sie gehen müssen, um einen umfassenden Überblick darüber zu erhalten, was Sie dem GC anvertrauen können und nicht zu tun, deshalb ist es zu einfach, der Sprache einfach zu misstrauen, weil der Zweck einer Sprache darin besteht, das Verhalten bis zu einem philosophischen Ausmaß zu kontrollieren (es ist für einen Programmierer, insbesondere für Anfänger, leicht, aufgrund bestimmter System- / Sprachverhalten in eine existenzielle Krise zu geraten) sind in der Lage zu tolerieren (und wenn Sie nicht können, werden Sie die Sprache erst verwenden, wenn Sie müssen), und mehr Dinge, die Sie nicht ohne bekannten Grund kontrollieren können, warum Sie sie nicht kontrollieren können, sind von Natur aus schädlich.
quelle
Die GC-Effizienz hängt von einer Reihe von Heuristiken ab. Eine häufig verwendete Heuristik ist beispielsweise, dass Schreibzugriffe auf Objekte normalerweise für Objekte erfolgen, die vor nicht allzu langer Zeit erstellt wurden. Ein weiterer Grund ist, dass viele Objekte sehr kurzlebig sind (einige Objekte werden für eine lange Zeit verwendet, aber viele werden einige Mikrosekunden nach ihrer Erstellung verworfen).
Anrufen
System.gc()
ist wie das Treten des GC. Es bedeutet: "all diese sorgfältig abgestimmten Parameter, diese intelligenten Organisationen, all die Anstrengungen, die Sie nur in die Zuordnung und Verwaltung der Objekte gesteckt haben, damit die Dinge reibungslos und gut ablaufen, einfach die ganze Menge fallen lassen und von vorne anfangen". Es kann die Leistung verbessern, aber meistens verschlechtert es nur die Leistung.Um
System.gc()
zuverlässig (*) zu verwenden, müssen Sie wissen, wie der GC in all seinen Details funktioniert. Solche Details ändern sich in der Regel erheblich, wenn Sie eine JVM eines anderen Anbieters oder die nächste Version desselben Anbieters oder derselben JVM verwenden, jedoch mit geringfügig unterschiedlichen Befehlszeilenoptionen. Daher ist es selten eine gute Idee, es sei denn, Sie möchten ein bestimmtes Problem ansprechen, bei dem Sie alle diese Parameter steuern. Daher der Begriff "schlechte Praxis": Das ist nicht verboten, die Methode existiert, aber sie zahlt sich selten aus.(*) Ich spreche hier von Effizienz.
System.gc()
wird nie brechen ein korrektes Java - Programm. Es wird auch keinen zusätzlichen Speicher heraufbeschwören, den die JVM sonst nicht hätte erhalten können: Vor dem Werfen einesOutOfMemoryError
erledigt die JVM die AufgabeSystem.gc()
, auch wenn dies ein letzter Ausweg ist.quelle
Manchmal ( nicht oft! ) Wissen Sie wirklich mehr über vergangene, aktuelle und zukünftige Speichernutzung als über die Laufzeit. Dies kommt nicht sehr oft vor, und ich würde behaupten, niemals in einer Webanwendung zu sein, während normale Seiten bereitgestellt werden.
Vor vielen Jahren arbeite ich an einem Berichtsgenerator
Erstens, da es nicht in Echtzeit war und die Benutzer erwarteten, auf einen Bericht zu warten, war eine Verzögerung während des GC-Laufs kein Problem, aber wir mussten Berichte mit einer Geschwindigkeit erstellen, die schneller war als angefordert.
Wenn man sich den obigen Überblick über den Prozess ansieht, ist klar, dass.
Daher hat es sich eindeutig gelohnt, einen GC-Lauf durchzuführen, wenn die Anforderungswarteschlange leer war. Das hatte keinen Nachteil.
Es kann sich lohnen, einen GC-Lauf durchzuführen, nachdem jeder Bericht per E-Mail gesendet wurde, da wir wissen, dass dies ein guter Zeitpunkt für einen GC-Lauf ist. Wenn der Computer jedoch über genügend RAM verfügt, werden bessere Ergebnisse erzielt, wenn der GC-Lauf verzögert wird.
Dieses Verhalten wurde auf Basis der einzelnen Installationen konfiguriert. Einige Kunden haben nach jedem Bericht einen erzwungenen GC aktiviert, wodurch der Schutz von Berichten erheblich beschleunigt wurde. (Ich gehe davon aus, dass dies auf den geringen Arbeitsspeicher auf dem Server zurückzuführen ist und viele andere Prozesse ausgeführt werden. Daher hat eine zeitlich erzwungene GC das Paging reduziert.)
Wir haben nie festgestellt, dass eine Installation, die nicht von Vorteil war, jedes Mal, wenn die Arbeitswarteschlange leer war, ein erzwungener GC-Lauf war.
Aber lassen Sie uns klar sein, das oben Genannte ist kein häufiger Fall.
quelle
Vielleicht schreibe ich beschissenen Code, aber mir ist klar geworden, dass das Klicken auf das Papierkorbsymbol bei Eclipse- und Netbeans-IDEs eine gute Vorgehensweise ist.
quelle
System.gc()
regelmäßig aufgerufen werden, ist das Verhalten wahrscheinlich ärgerlich.Erstens gibt es einen Unterschied zwischen Spezifikation und Realität. Die Spezifikation besagt, dass System.gc () ein Hinweis ist, dass GC ausgeführt werden sollte und die VM es ignorieren kann. Die Realität ist, dass die VM einen Aufruf von System.gc () niemals ignoriert.
Das Anrufen von GC ist mit einem nicht trivialen Aufwand verbunden. Wenn Sie dies zu einem zufälligen Zeitpunkt tun, werden Sie wahrscheinlich keine Belohnung für Ihre Bemühungen sehen. Andererseits ist es sehr wahrscheinlich, dass eine natürlich ausgelöste Sammlung die Kosten des Anrufs wieder wettmacht. Wenn Sie Informationen haben, die darauf hinweisen, dass ein GC ausgeführt werden soll, können Sie System.gc () aufrufen, und Sie sollten die Vorteile sehen. Ich habe jedoch die Erfahrung gemacht, dass dies nur in wenigen Fällen der Fall ist, da es sehr unwahrscheinlich ist, dass Sie über genügend Informationen verfügen, um zu verstehen, ob und wann System.gc () aufgerufen werden sollte.
Ein hier aufgeführtes Beispiel, das auf die Mülltonne in Ihrer IDE trifft. Wenn Sie zu einem Meeting gehen, treffen Sie es doch. Der Overhead wird Sie nicht beeinträchtigen und der Haufen wird möglicherweise aufgeräumt, wenn Sie zurückkommen. Tun Sie dies in einem Produktionssystem, und häufige Anrufe zum Sammeln bringen es zum Erliegen! Selbst gelegentliche Anrufe wie die von RMI können die Leistung beeinträchtigen.
quelle
Ja, das Aufrufen von System.gc () garantiert nicht, dass es ausgeführt wird. Es handelt sich um eine Anforderung an die JVM, die möglicherweise ignoriert wird. Aus den Dokumenten:
Es ist fast immer eine schlechte Idee, es zu nennen, da die automatische Speicherverwaltung normalerweise besser als Sie weiß, wann Sie gc verwenden müssen. Dies geschieht, wenn der interne Pool an freiem Speicher niedrig ist oder wenn das Betriebssystem die Rückgabe von Speicher anfordert.
Es kann akzeptabel sein, System.gc () aufzurufen, wenn Sie wissen, dass dies hilfreich ist . Damit meine ich, dass Sie das Verhalten beider Szenarien auf der Bereitstellungsplattform gründlich getestet und gemessen haben , und Sie können zeigen, dass es hilfreich ist. Beachten Sie jedoch, dass der GC nicht leicht vorhersehbar ist - er kann bei einem Lauf helfen und bei einem anderen weh tun.
quelle
Nach meiner Erfahrung ist die Verwendung von System.gc () effektiv eine plattformspezifische Form der Optimierung (wobei "Plattform" die Kombination aus Hardwarearchitektur, Betriebssystem, JVM-Version und möglicherweise mehr Laufzeitparametern wie verfügbarem RAM ist), da deren Verhalten Während sie auf einer bestimmten Plattform grob vorhersehbar sind, können (und werden) sie zwischen den Plattformen erheblich variieren.
Ja, es gibt Situationen, in denen System.gc () die (wahrgenommene) Leistung verbessert. Ein Beispiel ist, wenn Verzögerungen in einigen Teilen Ihrer App tolerierbar sind, in anderen jedoch nicht (das oben genannte Spielbeispiel, bei dem GC zu Beginn eines Levels und nicht während des Levels stattfinden soll).
Ob es hilft oder schadet (oder nichts tut), hängt jedoch stark von der Plattform ab (wie oben definiert).
Ich denke, es ist als plattformspezifische Optimierung der letzten Instanz gültig (dh wenn andere Leistungsoptimierungen nicht ausreichen). Aber Sie sollten es niemals nennen, nur weil Sie glauben, dass es helfen könnte (ohne bestimmte Benchmarks), weil es wahrscheinlich nicht hilft.
quelle
Da Objekte mithilfe des neuen Operators dynamisch zugewiesen
werden, fragen Sie sich möglicherweise, wie solche Objekte zerstört und ihr
Speicher für eine spätere Neuzuweisung freigegeben werden.
In einigen Sprachen, wie z. B. C ++, müssen dynamisch zugewiesene Objekte mithilfe eines Löschoperators manuell freigegeben werden.
quelle