Wenn das Programm Referenztyp-Entitäten wie Objekte, Arrays usw. erstellt, verteilt das System ein Stück Speicher für das Objekt im Heap-Speicher, und das Objekt wird in diesem Speicherstück gespeichert. Wenn dieses Stück Gedächtnis nicht mehr durch eine Referenzvariable verwiesen wird, wird das Gedächtnisstück zu Müll und wartet auf den Recycling des Müllsammungsmechanismus. Der Müllsammlermechanismus hat drei Merkmale:
Der Müllsammlungsmechanismus ist nur für das Recycling von Objekten im Heap -Speicher verantwortlich und recycelt weder physikalische Ressourcen (z. B. Datenbankverbindungen, geöffnete Dateiressourcen usw.) und recycelt den Speicher, der dem Objekt zugewiesen wurde, auch nicht auf die Art und Weise, wie ein Objekt angewendet wird (z. B. Speicher, die von der Objekt -Anrufe in der örtlichen Methode) angewendet werden, als das Objekt -Aufruf angewendet)
Das Programm kann den Betrieb der Müllsammlung nicht genau kontrollieren, sodass es nur für die Müllsammlung empfohlen werden kann. Es gibt zwei empfohlene Methoden: system.gc () und runtime.getRuntime (). Gc ()
Vor der Müllsammlung wird die Methode Finalize () immer zuerst bezeichnet, aber es ist dasselbe wie die Müllsammlung, und die Methode Finalize () ist auch nicht sicher.
In Bezug auf die oben genannten drei Merkmale gibt es drei Probleme:
1. Die Reinigungsarbeit muss manuell durchgeführt werden, um das Gedächtnis und andere physische Ressourcen auf eine andere Weise als das Erstellen von Objekten zu befreien. Und achten Sie darauf, abgelaufene Objektreferenzen zu beseitigen, ansonsten können OOM verursacht werden.
Die manuelle Reinigung verwendet normalerweise eine Codestruktur wie Try ... Endlich ...
Beispiele sind wie folgt:
importieren java.io.fileinputstream; import java.io.filenotfoundException; import java.io.ioxception; public class ManualClear {public static void main (String [] args) {FileInputStream FileInputStream = null; try {FileInputStream = new FileInputStream ("./ Src/ManualClear.java"); } catch (FilenotFoundException e) {System.out.println (e.getMessage ()); E. printstacktrace (); zurückkehren; } try {byte [] bbuf = new Byte [1024]; int hasread = 0; try {while ((hasRead = fileInputStream.read (bbuf))> 0) {System.out.println (neuer String (BBUF, 0, HasRead)); }} catch (ioException e) {e.printstacktrace (); }} schließlich {try {FileInputStream.close (); } catch (ioException e) {e.printstacktrace (); }}}}In der Regel gibt es drei gemeinsame OOM -Fälle, die durch Bezugnahme auf abgelaufene Objekte verursacht werden. Diese drei Fälle sind normalerweise nicht leicht zu erkennen, und es wird in kurzer Zeit keine Probleme geben, die in kurzer Zeit laufen. Nach langer Zeit wird die Anzahl der durchgesickerten Objekte jedoch letztendlich zum Absturz des Programms führen.
Wenn die Klasse den Speicher für sich selbst verwaltet, sollten Sie sich wie folgt vor Speicherlecks beachten:
Import Java.util.Arrays; Import Java.util.EmptyStackexception; Klasse Stack {private Object [] Elemente; private intgröße; private statische endgültige int default_inital_capacity = 16; public stack () {Elements = neues Objekt [default_inital_capacity]; } public void push (Objekt e) {sealEcapacity (); Elemente [Größe ++] = e; } public Object pop () {if (size == 0) {throw New leerStackexception (); } Rückgabeelemente [-Größe]; } private void sealecapacity () {if (Elements.length == Größe) {Elements = arrays.copyof (Elemente, 2 * Größe + 1); }}} öffentliche Klasse StackDemo {public static void main (String [] args) {stack stack = new Stack (); für (int i = 0; i <10000; i ++) {stack.push (neues Objekt ()); } für (int i = 0; i <10000; i ++) {stack.pop (); }}}Der Grund für Speicherlecks ist, dass selbst wenn andere Objekte auf dem Stapel nicht mehr verwiesen werden, das Element [] Array in der Stapelklasse immer noch Verweise auf diese Objekte enthält, was dazu führt, dass die Objekte nicht von der Müllsammlung recycelt werden. Wenn die Klasse selbst den Speicher selbst verwalten muss, achten Sie darauf, ob diese abgelaufenen Referenzen, die von intern aufrechterhalten werden, rechtzeitig Derferenziert sind. In diesem Beispiel wird erst nach der Veröffentlichung des Stacks der angezeigte One angezeigt.
Elemente [Größe] = NULL;
Der Cache soll vor Speicherlecks vorsichtig sein. Diese Situation ist normalerweise der Fall, dass es wahrscheinlich leicht zu vergessen ist, wenn das Objekt in den Cache gesteckt wird, ob es nicht lange nicht verwendet wird. Normalerweise kann WakehasMap verwendet werden, um den Cache darzustellen. Nach Ablauf der Elemente im Cache können sie automatisch gelöscht werden. Oder es kann regelmäßig von einem Hintergrund -Thread ausgeführt werden, um abgelaufene Elemente im Puffer zu löschen.
Die Registrierung von Hörern oder Rückrufen wird am besten auf Unregister angezeigt.
2. Rufen Sie nicht endgültig () manuell an, es wird zum Müllsammler gerufen
3.. Vermeiden Sie die Verwendung der Finalize () -Methode, es sei denn, sie wird als Beurteilung der Endbedingung verwendet, um festzustellen, dass das Objekt nicht ordnungsgemäß gereinigt wurde. Es wird als Sicherheitsnetzwerk verwendet, um Systemressourcen aufzuräumen, wenn man vergessene Anrufe manuell bereinigt. Eine verzögerte Reinigung sollte nicht gereinigt werden. Wenn Sie gleichzeitig die Informationen über die vergessene Reinigungsressource aufzeichnen, ist es auch zweckmäßig, dass Fehler später entdeckt und den vergessenen Reinigungscode rechtzeitig geändert werden. Frei machen die nicht sehr kritischen Systemressourcen, die von der lokalen Methode im Objekt erhalten wurden.
Da die Methode Finalize () nicht genau sichergestellt ist, ist es am besten, Schlüsselressourcen zu veröffentlichen, kann jedoch in den drei oben genannten Fällen verwendet werden. Der erste Fall ist wie folgt:
Klassenbuch {boolean checkout = false; public book (boolean checkout) {this.Checkout = checkout; } public void checkin () {checkout = false; } @Override protected void enddefination () löscht Throwable {if (Checkout) {System.out.println ("Fehler: Checkout"); }}} public class FinalizeCheckObjectuse {public static void main (String [] args) {neues Buch (wahr); System.gc (); }}Ausführungsergebnisse:
Fehler: Überprüfen Sie
Das Buchobjekt im Beispiel muss vor der Veröffentlichung im Checkin -Zustand enthalten sein, andernfalls kann es nicht veröffentlicht werden. Die Implementierung in der Finalize kann dazu beitragen, illegale Objekte rechtzeitig oder direkter zu entdecken, um eine Referenzvariable zu verwenden, um sie in der Finalisation direkt darauf zu verweisen, damit sie in den Status der erreichbaren Ausstattung eintreten und sie dann erneut verarbeiten kann.
Ein weiterer Punkt ist, dass, wenn die Unterklasse die Abschlussmethode der übergeordneten Klasse überschreibt, aber vergibt, Super.finalize manuell aufzurufen, oder der Abschlussprozess der Unterklasse eine Ausnahme hat, was dazu führt, dass Super.finalisierung nicht ausgeführt wird, wird die Endmethode der übergeordneten Klasse niemals aufgerufen.
wie folgt:
Klasse übergeordnet {@Override Protected void Finalize () löscht Throwable {System.out.println (getClass (). getName () + "finalize start"); }} class Son erweitert übergeordnetes {@Override protected void Finalize (). }} öffentliche Klasse Superfinalizelost {public static void main (String [] args) {new Son (); System.gc (); }}Auslaufergebnisse:
Sohn endende Start
oder
Klasse übergeordnet {@Override Protected void Finalize () löscht Throwable {System.out.println (getClass (). getName () + "finalize start"); }} class Son erweitert übergeordnetes {@Override protected void Finalize (). int i = 5/0; super.finalize (); }} öffentliche Klasse Superfinalizelost {public static void main (String [] args) {new Son (); System.gc (); }}Ausführungsergebnisse:
Sohn endende Start
Für den zweiten Fall können Sie den Versuch verwenden ... endlich ... Struktur, um ihn zu lösen, aber für den ersten Fall ist es besser, eine Methode namens Endmethode Guardian zu verwenden. Das Beispiel ist wie folgt
Klasse parent2 {private endgültiges Objekt endgültige Guardian = new Object () {Protected void endgleeize () löst Throwable {System.out.println aus ("Die Logik in der übergeordneten Klassenabschlussmethode hier ausführen"); }; };} class Son2 erweitert parent2 {@Override protected void Finalize () löscht Throwable {System.out.println (getClass (). GetName () + "finalize start"); int i = 5/0; super.finalize (); }} public class FinalizeGuardian {public static void main (String [] args) {new Son2 (); System.gc (); }}Ausführungsergebnisse:
Führen Sie hier die Logik in der übergeordneten Klassenabschlussmethode aus
SON2 Finalize Start
Dies stellt sicher, dass die in der Endmethode der übergeordneten Klasse erforderlichen Operationen ausgeführt werden.
Das Obige dreht sich alles um diesen Artikel, ich hoffe, es wird für das Lernen aller hilfreich sein.