Gibt es eine Möglichkeit, Speicher in Java freizugeben, ähnlich wie bei C free()
? Oder ist es die einzige Option, das Objekt auf null zu setzen und sich auf GC zu verlassen?
java
garbage-collection
Felix
quelle
quelle
Antworten:
Java verwendet verwalteten Speicher. Sie können also nur mithilfe des
new
Operators Speicher zuweisen. Die einzige Möglichkeit, Speicher freizugeben, besteht darin, sich auf den Garbage Collector zu verlassen.Dieses Whitepaper zur Speicherverwaltung (PDF) kann Ihnen helfen, zu erklären, was los ist.
Sie können auch anrufen,
System.gc()
um vorzuschlagen, dass der Garbage Collector sofort ausgeführt wird. Die Java Runtime trifft jedoch die endgültige Entscheidung, nicht Ihren Code.Gemäß der Java - Dokumentation ,
quelle
System.gc()
völlig ignorieren .Niemand scheint erwähnt zu haben, dass explizit Objektreferenzen festgelegt werden. Dies
null
ist eine legitime Technik, um Speicher freizugeben, den Sie möglicherweise in Betracht ziehen möchten.Angenommen, Sie haben
List<String>
am Anfang einer Methode, deren Größe sehr groß wurde, eine deklariert , die jedoch nur bis zur Hälfte der Methode erforderlich war. Zu diesem Zeitpunkt können Sie die Listenreferenz so einstellennull
, dass der Garbage Collector dieses Objekt möglicherweise zurückfordern kann, bevor die Methode abgeschlossen ist (und die Referenz ohnehin nicht mehr gültig ist).Beachten Sie, dass ich diese Technik in der Realität selten verwende, aber es lohnt sich, sie in Betracht zu ziehen, wenn Sie mit sehr großen Datenstrukturen arbeiten.
quelle
Nicht empfohlen.
Bearbeiten: Ich habe die ursprüngliche Antwort im Jahr 2009 geschrieben. Es ist jetzt 2015.
Müllsammler sind in den ~ 20 Jahren, in denen Java existiert, immer besser geworden. Wenn Sie den Garbage Collector manuell aufrufen, sollten Sie an dieser Stelle andere Ansätze in Betracht ziehen:
quelle
* "Ich persönlich verlasse mich auf das Nullstellen von Variablen als Platzhalter für das zukünftige ordnungsgemäße Löschen. Zum Beispiel nehme ich mir die Zeit, alle Elemente eines Arrays zu annullieren, bevor ich das Array selbst lösche (null mache)."
Dies ist nicht erforderlich. Der Java GC funktioniert so, dass er Objekte findet, auf die nicht verwiesen wird. Wenn ich also ein Objekt x mit einer Referenz (= Variable) a habe, die darauf verweist, wird es vom GC nicht gelöscht, da es eine Referenz gibt zu diesem Objekt:
Wenn Sie a null setzen, geschieht Folgendes:
X hat jetzt keinen Verweis darauf und wird gelöscht. Dasselbe passiert, wenn Sie a so einstellen, dass es auf ein anderes Objekt als x verweist.
Wenn Sie also ein Array arr haben, das auf die Objekte x, y und z verweist, und eine Variable a, die auf das Array verweist, sieht es so aus:
Wenn Sie a null setzen, geschieht Folgendes:
Der GC stellt fest, dass arr keinen Verweis darauf hat, und löscht es, wodurch Sie diese Struktur erhalten:
Jetzt findet der GC x, y und z und löscht sie ebenfalls. Das Nullstellen jeder Referenz im Array macht nichts besser, es verbraucht nur CPU-Zeit und Speicherplatz im Code (das heißt, es wird nicht weiter schaden. Der GC wird weiterhin in der Lage sein, die Leistung zu erbringen, die er sollte ).
quelle
Ein triftiger Grund für den Wunsch, Speicher von einem Programm (Java oder nicht) freizugeben, besteht darin, anderen Programmen auf Betriebssystemebene mehr Speicher zur Verfügung zu stellen. Wenn meine Java-Anwendung 250 MB verwendet, möchte ich sie möglicherweise auf 1 MB reduzieren und die 249 MB für andere Apps verfügbar machen.
quelle
Um die Antwort und den Kommentar von Yiannis Xanthopoulos und Hot Licks zu erweitern (Entschuldigung, ich kann noch keinen Kommentar abgeben!), Können Sie VM-Optionen wie in diesem Beispiel festlegen:
In meinem JDK 7 wird dann nicht verwendeter VM-Speicher freigegeben, wenn mehr als 30% des Heapspeichers nach dem GC frei werden, wenn die VM inaktiv ist. Sie müssen diese Parameter wahrscheinlich anpassen.
Obwohl ich es im folgenden Link nicht hervorgehoben gesehen habe, beachten Sie, dass einige Garbage Collectors diese Parameter möglicherweise nicht einhalten und Java standardmäßig einen davon für Sie auswählt, falls Sie mehr als einen Kern haben (daher das obige Argument UseG1GC) ).
VM-Argumente
Update: Für Java 1.8.0_73 habe ich gesehen, dass die JVM gelegentlich kleine Mengen mit den Standardeinstellungen veröffentlicht. Scheint dies nur zu tun, wenn ~ 70% des Heaps nicht verwendet werden. Ich weiß nicht, ob es aggressiver wäre, wenn das Betriebssystem nur wenig physischen Speicher hätte.
quelle
Ich habe damit experimentiert.
Es ist wahr, dass
System.gc();
nur vorgeschlagen wird, den Garbage Collector auszuführen.Wenn Sie jedoch
System.gc();
nach dem Festlegen aller Verweise auf anrufennull
, werden Leistung und Speicherbelegung verbessert.quelle
Wenn Sie wirklich einen Speicherblock zuweisen und freigeben möchten, können Sie dies mit direkten ByteBuffers tun. Es gibt sogar eine nicht tragbare Möglichkeit, den Speicher freizugeben.
Wie bereits erwähnt, bedeutet dies jedoch keine gute Idee, dies zu tun, nur weil Sie Speicher in C freigeben müssen.
Wenn Sie der Meinung sind, dass Sie wirklich einen guten kostenlosen Anwendungsfall haben (), fügen Sie ihn bitte in die Frage ein, damit wir sehen können, was Sie tun möchten. Es ist sehr wahrscheinlich, dass es einen besseren Weg gibt.
quelle
Ganz von javacoffeebreak.com/faq/faq0012.html
quelle
In meinem Fall möchte ich, da mein Java-Code in naher Zukunft in andere Sprachen portiert werden soll (hauptsächlich C ++), zumindest ein Lippenbekenntnis zur ordnungsgemäßen Speicherfreigabe ablegen, damit er später den Portierungsprozess erleichtert.
Ich persönlich verlasse mich darauf, Variablen als Platzhalter für das zukünftige ordnungsgemäße Löschen auf Null zu setzen. Zum Beispiel nehme ich mir die Zeit, um alle Elemente eines Arrays zu annullieren, bevor ich das Array selbst lösche (null mache).
Aber mein Fall ist sehr speziell und ich weiß, dass ich dabei Leistungstreffer mache.
quelle
* "Angenommen, Sie haben eine Liste am Anfang einer Methode deklariert, deren Größe sehr groß wurde, die jedoch erst nach der Hälfte der Methode erforderlich war. Zu diesem Zeitpunkt können Sie den Listenverweis auf null setzen damit der Garbage Collector dieses Objekt möglicherweise zurückfordern kann, bevor die Methode abgeschlossen ist (und die Referenz ohnehin außerhalb des Gültigkeitsbereichs liegt). " * *
Dies ist korrekt, aber diese Lösung ist möglicherweise nicht verallgemeinerbar. Während Sie einen List-Objektverweis auf null setzen, wird Speicher für die Garbage Collection verfügbar gemacht, gilt dies nur für ein List-Objekt primitiver Typen. Wenn das Listenobjekt stattdessen Referenztypen enthält, wird durch Setzen des Listenobjekts = null keine der in der Liste enthaltenen Referenztypen dereferenziert. In diesem Fall werden durch Festlegen des Listenobjekts = null die enthaltenen Referenztypen verwaist, deren Objekte nicht für die Speicherbereinigung verfügbar sind, es sei denn, der Algorithmus für die Speicherbereinigung ist intelligent genug, um festzustellen, ob die Objekte verwaist sind.
quelle
Obwohl Java eine automatische Speicherbereinigung bietet, möchten Sie manchmal wissen, wie groß das Objekt ist und wie viel davon noch übrig ist. Freier Speicher wird programmgesteuert verwendet,
import java.lang;
undRuntime r=Runtime.getRuntime();
um Speicherwerte zu erhalten, indem Siemem1=r.freeMemory();
den freien Speicher verwenden, rufen Sie dier.gc();
Methode und den Aufruf auffreeMemory()
quelle
Von JAVA wird empfohlen, null zuzuweisen
Von https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
quelle