Ist es möglich, die Speicherbereinigung in Java zu erzwingen, auch wenn dies schwierig ist? Ich weiß von System.gc();
und Runtime.gc();
aber sie schlagen nur vor, GC zu machen. Wie kann ich GC erzwingen?
java
garbage-collection
Robert Columbia
quelle
quelle
Antworten:
Am besten rufen Sie an,
System.gc()
was lediglich ein Hinweis für den Garbage Collector ist, dass er eine Sammlung durchführen soll. Es gibt jedoch keine Möglichkeit, eine sofortige Sammlung zu erzwingen, da der Garbage Collector nicht deterministisch ist.quelle
non-deterministic == trouble
GC.Collect()
nicht. In Javagc()
tut.Die jlibs-Bibliothek verfügt über eine gute Dienstprogrammklasse für die Speicherbereinigung . Mit WeakReference- Objekten können Sie die Speicherbereinigung mit einem kleinen Trick erzwingen .
RuntimeUtil.gc () aus den jlibs:
quelle
PhantomReference
mit a zu verwenden,ReferenceQueue
und dann würden Sie nach der Finalisierung, aber noch vor der Bereinigung benachrichtigt. Selbst wenn Sie erfolgreich feststellen würden, dass der Speicher für dieses Objekt zurückgefordert wurde, würde dies in einem Generations-GC wie dem von HotSpot immer noch sehr wenig bedeuten. Normalerweise würde es mit der Säuberung der jungen Generation zusammenfallen.System.gc(); System.gc();
, aber es wäre sicher interessant zu wissen, ob es jemals besser funktioniert hat. In der TatSystem.gc()
würde es ausreichen , nur zu drucken, wie oft es aufgerufen wurde . Die Chance, jemals 2 zu erreichen, ist ziemlich gering.Der beste (wenn nicht nur) Weg, einen GC zu erzwingen, wäre das Schreiben einer benutzerdefinierten JVM. Ich glaube, die Garbage Collectors sind steckbar, sodass Sie wahrscheinlich nur eine der verfügbaren Implementierungen auswählen und optimieren können.
Hinweis: Dies ist keine einfache Antwort.
quelle
Verwenden der Java ™ Virtual Machine Tool-Schnittstelle (JVM TI) die Funktion
wird "Die VM zwingen, eine Garbage Collection durchzuführen." Die JVM TI ist Teil der JavaTM Platform Debugger Architecture (JPDA) .
quelle
JA, es ist fast möglich zu erzwingen, dass Sie Methoden in derselben Reihenfolge aufrufen müssen, und gleichzeitig sind dies:
Selbst wenn es sich nur um ein Objekt handelt, um die Verwendung dieser beiden Methoden gleichzeitig zu bereinigen, wird der Garbage Collector gezwungen, die
finalise()
Methode des nicht erreichbaren Objekts zu verwenden, um den zugewiesenen Speicher freizugeben und die Anweisungen derfinalize()
Methode auszuführen.JEDOCH es eine schreckliche Praxis ist die Garbage Collector zu verwenden , da die Verwendung von ihm könnte eine Überlast auf die Software einzuführen, die noch schlimmer als auf dem Speicher sein können, hat der Garbage Collector seinen eigenen Thread , die nicht möglich ist , zu steuern und je nach Der vom GC verwendete Algorithmus kann mehr Zeit in Anspruch nehmen und wird als sehr ineffizient angesehen. Sie sollten Ihre Software mit Hilfe des GC überprüfen, wenn er am schlimmsten ist, da er definitiv kaputt ist. Eine gute Lösung darf nicht vom GC abhängen.
HINWEIS: Nur um zu bedenken, dass dies nur funktioniert, wenn bei der Finalisierungsmethode keine Neuzuweisung des Objekts erfolgt. In diesem Fall bleibt das Objekt am Leben und es wird eine technisch mögliche Auferstehung auftreten.
quelle
gc()
ist dies nur ein Hinweis zum Ausführen einer Garbage Collection.runFinalizers()
führt Finalizer nur für Objekte aus, "die als verworfen befunden wurden". Wenn der GC nicht tatsächlich ausgeführt wurde, gibt es möglicherweise keine solchen Objekte ...In der Dokumentation zu OutOfMemoryError wird angegeben , dass es nicht ausgelöst wird, es sei denn, die VM konnte nach einer vollständigen Speicherbereinigung keinen Speicher zurückfordern. Wenn Sie also weiterhin Speicher zuweisen, bis Sie den Fehler erhalten, haben Sie bereits eine vollständige Speicherbereinigung erzwungen.
Vermutlich war die Frage, die Sie wirklich stellen wollten, "Wie kann ich die Erinnerung zurückgewinnen, von der ich denke, dass ich sie durch Speicherbereinigung zurückgewinnen sollte?"
quelle
So fordern Sie GC manuell an (nicht von System.gc ()):
quelle
.gc ist ein Kandidat für die Eliminierung in zukünftigen Versionen - ein Sun Engineer hat einmal kommentiert, dass vielleicht weniger als zwanzig Menschen auf der Welt tatsächlich wissen, wie man .gc () verwendet - ich habe letzte Nacht einige Stunden an einer zentralen / kritischen Stelle gearbeitet Datenstruktur unter Verwendung von SecureRandom-generierten Daten, bei etwas mehr als 40.000 Objekten würde die VM langsamer werden, als ob ihr die Zeiger ausgegangen wären. Offensichtlich verschluckte es sich an 16-Bit-Zeigertabellen und zeigte ein klassisches Verhalten bei "fehlerhaften Maschinen".
Ich versuchte -Xms und so weiter, drehte weiter, bis es ungefähr 57, xxx etwas werden würde. Dann würde es gc von etwa 57.127 auf 57.128 nach einem gc () laufen lassen - ungefähr so schnell wie das Code-Bloat im Camp Easy Money.
Ihr Design muss grundlegend überarbeitet werden, wahrscheinlich mit einem Schiebefenster.
quelle
Sie können einen GC über die Befehlszeile auslösen. Dies ist nützlich für Batch / Crontab:
Sehen :
quelle
Die JVM-Spezifikation sagt nichts Spezifisches über die Speicherbereinigung aus. Aus diesem Grund steht es den Anbietern frei, GC auf ihre Weise zu implementieren.
Diese Unbestimmtheit führt also zu Unsicherheit im Verhalten der Speicherbereinigung. Sie sollten Ihre JVM-Details überprüfen, um Informationen zu den Garbage Collection-Ansätzen / -Algorithmen zu erhalten. Es gibt auch Optionen zum Anpassen des Verhaltens.
quelle
Wenn Sie die Speicherbereinigung erzwingen müssen, sollten Sie möglicherweise überlegen, wie Sie Ressourcen verwalten. Erstellen Sie große Objekte, die im Speicher verbleiben? Erstellen Sie große Objekte (z. B. Grafikklassen) mit einer
Disposable
Schnittstelle und rufen Sie nicht auf,dispose()
wenn Sie damit fertig sind? Erklären Sie etwas auf Klassenebene, das Sie nur innerhalb einer einzigen Methode benötigen?quelle
Es wäre besser, wenn Sie den Grund beschreiben würden, warum Sie eine Speicherbereinigung benötigen. Wenn Sie SWT verwenden, können Sie Ressourcen wie
Image
undFont
zur Speicherfreigabe bereitstellen. Zum Beispiel:Es gibt auch Tools zum Ermitteln nicht verfügbarer Ressourcen.
quelle
Wenn Ihnen der Speicher ausgeht und
OutOfMemoryException
Sie einen Speicherplatz erhalten, können Sie versuchen, den für Java verfügbaren Heap-Speicherplatz zu erhöhen, indem Sie Ihr Programm mitjava -Xms128m -Xmx512m
statt nur startenjava
. Dies gibt Ihnen eine anfängliche Heap-Größe von 128 MB und ein Maximum von 512 MB, was weit mehr als die Standardgröße von 32 MB / 128 MB ist.quelle
java -Xms512M -Xmx1024M
Eine andere Möglichkeit besteht darin, keine neuen Objekte zu erstellen.
Objektpooling ist weg, um den GC-Bedarf in Java zu verringern.
Das Objekt-Pooling ist im Allgemeinen nicht schneller als die Objekterstellung (insbesondere für Lightweight-Objekte), aber schneller als die Garbage Collection. Wenn Sie 10.000 Objekte erstellt haben und jedes Objekt 16 Byte groß war. Das sind 160.000 Bytes, die GC zurückfordern muss. Wenn Sie jedoch nicht alle 10.000 gleichzeitig benötigen, können Sie einen Pool zum Recyceln / Wiederverwenden der Objekte erstellen, sodass keine neuen Objekte erstellt werden müssen und keine alten Objekte mehr analysiert werden müssen.
So etwas (ungetestet). Und wenn Sie möchten, dass es threadsicher ist, können Sie die LinkedList gegen eine ConcurrentLinkedQueue austauschen.
quelle
Unter OracleJDK 10 mit G1 GC führt ein einziger Aufruf von
System.gc()
dazu, dass GC die alte Sammlung bereinigt. Ich bin nicht sicher, ob GC sofort ausgeführt wird. GC bereinigt die Young Collection jedoch nicht, selbst wennSystem.gc()
sie mehrmals in einer Schleife aufgerufen wird. Damit GC die Young Collection bereinigt, müssen Sie in einer Schleife (z . B.new byte[1024]
) ohne Aufruf zuweisenSystem.gc()
. Wenn SieSystem.gc()
aus irgendeinem Grund anrufen, kann GC die Young Collection nicht bereinigen.quelle
Das ist richtig, nur Geste. Sie haben so ziemlich die Standardantworten, die bereits von mehreren Postern gegeben wurden. Nehmen wir dies eins nach dem anderen:
Richtig, es gibt kein tatsächliches JVM - dies ist nur eine Spezifikation, eine Menge Informatik, die ein gewünschtes Verhalten beschreibt ... Ich habe mich kürzlich mit der Initialisierung von Java-Objekten aus nativem Code befasst. Um das zu bekommen, was Sie wollen, müssen Sie nur das tun, was als aggressives Nullen bezeichnet wird. Die Fehler, wenn sie falsch gemacht werden, sind so schlimm, dass wir uns auf den ursprünglichen Umfang der Frage beschränken müssen:
Bei den meisten Postern hier wird davon ausgegangen, dass Sie an einer Schnittstelle arbeiten. In diesem Fall müssten wir prüfen, ob Ihnen jeweils das gesamte Objekt oder ein Objekt übergeben wird.
Wenn Sie kein Objekt mehr benötigen, können Sie dem Objekt null zuweisen. Wenn Sie es jedoch falsch verstehen, wird eine Nullzeigerausnahme generiert. Ich wette, Sie können eine bessere Arbeit erzielen, wenn Sie NIO verwenden
Jedes Mal, wenn Sie, ich oder jemand anderes sagt: " Bitte, ich brauche das fürchterlich. " Es ist fast ein universeller Vorläufer für die fast vollständige Zerstörung dessen, woran Sie arbeiten möchten tatsächlich verwendeter Code und zeigen Sie uns Ihre Frage.
Sei nicht frustriert. Oft führt dies dazu, dass Ihre Datenbank ein Paket verwendet, das irgendwo gekauft wurde, und das ursprüngliche Design nicht für massive Datenstrukturen optimiert ist.
Das ist sehr häufig.
quelle
Zu Ihrer Information
Der Methodenaufruf System.runFinalizersOnExit (true) garantiert, dass Finalizer-Methoden aufgerufen werden, bevor Java heruntergefahren wird. Diese Methode ist jedoch von Natur aus unsicher und veraltet. Eine Alternative besteht darin, mit der Methode Runtime.addShutdownHook "Shutdown Hooks" hinzuzufügen.
Masarrat Siddiqui
quelle
Es gibt eine indirekte Möglichkeit, den Garbage Collector zu erzwingen. Sie müssen den Heap nur mit temporären Objekten füllen, bis der Garbage Collector ausgeführt wird. Ich habe eine Klasse erstellt, die den Garbage Collector auf diese Weise zwingt:
Verwendung:
Ich weiß nicht , wie viel diese Methode ist nützlich, weil es Haufen ständig füllt, aber wenn Sie unternehmenskritische Anwendung, die MUST GC zwingen - wenn dies kann die Java tragbare Weg zu GC zu erzwingen.
quelle
Ich möchte hier etwas hinzufügen. Bitte beachten Sie, dass Java nicht auf einer virtuellen Maschine und nicht auf einer tatsächlichen Maschine ausgeführt wird. Die virtuelle Maschine hat ihre eigene Art der Kommunikation mit der Maschine. Es kann von System zu System variieren. Wenn wir jetzt den GC aufrufen, bitten wir die virtuelle Maschine von Java, den Garbage Collector aufzurufen.
Da sich der Garbage Collector in der virtuellen Maschine befindet, können wir ihn nicht zwingen, dort und dann eine Bereinigung durchzuführen. Vielmehr stellen wir unsere Anfrage beim Garbage Collector in die Warteschlange. Dies hängt von der virtuellen Maschine ab. Nach einer bestimmten Zeit (dies kann sich von System zu System ändern, im Allgemeinen, wenn der der JVM zugewiesene Schwellenwertspeicher voll ist) gibt die tatsächliche Maschine den Speicherplatz frei. : D.
quelle
Der folgende Code stammt aus der Methode assertGC (...). Es versucht, den nichtdeterministischen Garbage Collector zum Sammeln zu zwingen.
Quelle (aus Gründen der Übersichtlichkeit habe ich einige Kommentare hinzugefügt): NbTestCase-Beispiel
quelle
Sie können versuchen,
Runtime.getRuntime().gc()
die Dienstprogrammmethode zu verwenden oder zu verwenden.System.gc()
Hinweis: Diese Methoden gewährleisten keine GC. Und ihr Umfang sollte auf JVM beschränkt sein, anstatt sie programmgesteuert in Ihrer Anwendung zu behandeln.quelle
Wenn Sie JUnit und Spring verwenden, fügen Sie dies in jeder Testklasse hinzu:
quelle