Heim >Java >javaLernprogramm >Studiennotizen zur JAVA-Virtual-Machine: Garbage-Collection-Methode im JVM-Speichermodell
Im letzten Artikel wurden die relevanten Kenntnisse des JVM-Speichermodells vorgestellt. Tatsächlich gibt es einige Inhalte, die ausführlicher vorgestellt werden können, z. B. das dynamische Einfügen von Konstantenpools zur Laufzeit, den direkten Speicher usw. Ich werde das übernehmen Zeit, den vorherigen Blog später zu verbessern. Stellen Sie einige Garbage-Collection-Strategien in JVM vor.
1. Die finishize()-Methode Wenn das Objekt keine Referenzen hat, wird das Objekt normalerweise recycelt. Was aber, wenn wir einige Vorgänge ausführen möchten, bevor das Objekt recycelt wird, z. B. das Schließen einiger Ressourcen oder das Wiederbeleben des Objekts, um zu verhindern, dass es recycelt wird? In diesem Fall wird die Finalize-Methode verwendet. Die Methode finailize ist eine in der Object-Klasse definierte Methode, was bedeutet, dass jedes Objekt über diese Methode verfügt. Wenn das Objekt jedoch nach der Wiederbelebung erneut aufgerufen wird, wird die Methode finalize nicht aufgerufen, und die Priorität ist relativ niedrig, und es gibt keine Garantie dafür ausgeführt werden, daher wird die Verwendung der Finalize-Methode nicht empfohlen. Zusammenfassend gibt es drei Funktionen: ①, GC wurde zuvor aufgerufen. ②. Es wird nur einmal aufgerufen. ③. Die Ausführung ist unzuverlässig und die Verwendung von
wird nicht empfohlen. Informationen zur Verwendung von finalize finden Sie im folgenden Code:1 public class FinalizeTest { 2 3 private static FinalizeTest test; 4 /** 5 * VM参数:-XX: +PrintGCDetails -Xmx=1M -Xms=1M 6 * 7 * @param args 8 */ 9 public static void main(String[] args) { 10 //先对test对象赋值 11 test = new FinalizeTest(); 12 int _1m = 1024 * 1024; 13 //将test置为null,便于回收 14 test = null; 15 try { 16 System.gc(); 17 //模拟睡眠5s,finalize优先级较低,保证finalize能执行 18 Thread.sleep(5000); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } 22 if (test != null) { 23 System.out.println("first,i am alive"); 24 }else{ 25 System.out.println("first,i am dead"); 26 } 27 //由于test在finalize方法里复活了,再次将test置为null 28 test = null; 29 try { 30 System.gc(); 31 Thread.sleep(5000);//模拟睡眠5s,让GC回收 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 if (test != null) { 36 System.out.println("second,i am alive"); 37 }else{ 38 System.out.println("second,i am dead"); 39 } 40 41 } 42 @Override 43 protected void finalize() throws Throwable { 44 test = this ; 45 System.out.println("finalize excuted"); 46 super.finalize(); //调用父类的finailize方法 47 } 48 }
Das Ergebnis der Ausführung dieses Codes ist wie folgt:
Wie Sie sehen können, wird das Testobjekt nach der Ausführung der finalize-Methode reaktiviert, sodass zunächst „i am alive“ gedruckt wird. Aber während des zweiten GC wurde die finalize-Methode nicht ausgeführt, also wurde als zweites „I am dead“ gedruckt. Wie bereits erwähnt, hat finalize eine niedrige Priorität und ist unzuverlässig. Wenn kein Thread.sleep(5000) vorhanden ist, schauen wir uns den Code und die Ergebnisse an:
1 public class FinalizeTest { 2 3 private static FinalizeTest test; 4 /** 5 * VM参数:-XX: +PrintGCDetails -Xmx=1M -Xms=1M 6 * 7 * @param args 8 */ 9 public static void main(String[] args) { 10 //先对test对象赋值 11 test = new FinalizeTest(); 12 int _1m = 1024 * 1024; 13 //将test置为null,便于回收 14 test = null; 15 try { 16 System.gc(); 17 //模拟睡眠5s,finalize优先级较低,保证finalize能执行 18 //不执行睡眠操作,Thread.sleep(5000); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 if (test != null) { 23 System.out.println("first,i am alive"); 24 }else{ 25 System.out.println("first,i am dead"); 26 } 27 //由于test在finalize方法里复活了,再次将test置为null 28 test = null; 29 try { 30 System.gc(); 31 //不执行睡眠操作,Thread.sleep(5000);//模拟睡眠5s,让GC回收 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 if (test != null) { 36 System.out.println("second,i am alive"); 37 }else{ 38 System.out.println("second,i am dead"); 39 } 40 41 } 42 @Override 43 protected void finalize() throws Throwable { 44 test = this ; 45 System.out.println("finalize excuted"); 46 super.finalize(); //调用父类的finailize方法 47 } 48 }
Die laufenden Ergebnisse sind wie folgt:
Hier ist deutlich zu erkennen, dass die Priorität der Finalize-Methode relativ niedrig ist.
Überlegungen zu diesem Beispiel: Der erste Teil des Codes in diesem Beispiel wird unter Bezugnahme auf den Code in „Ausführliches Verständnis der Java Virtual Machine“ implementiert, aber ich habe immer das Gefühl, dass es zwei Fragen gibt: Warum? Existiert das mit statischen Mitgliedsvariablen modifizierte Testobjekt? Wenn es sich um eine statische Änderung handelt, gibt es einen Methodenbereich, und der GC-Effekt im Methodenbereich ist normalerweise nicht sehr gut. Das andere liegt in Form von Mitgliedsvariablen vor, sodass beim Recycling von Finalize nicht das Recycling des aktuellen Objekts selbst widergespiegelt wird. Daher halte ich dieses Beispiel für nicht sehr gut.2. Referenzzählmethode
Die Referenzzählmethode ist ein früherer GC-Recycling-Algorithmus, der derzeit im Allgemeinen nicht verwendet wird Ja:
Jedes Objekt verwaltet einen Referenzzähler mit einem Anfangswert von 0. Wenn auf ein Objekt verwiesen wird, wird der Referenzzähler des Objekts um 1 erhöht. Wenn es nicht referenziert wird, wird der Referenzzähler des Objekts um 1 dekrementiert Wenn der Referenzzähler eines Objekts 0 wird, gilt das Objekt als recycelbar . Die Vor- und Nachteile dieser Methode liegen auf der Hand. Die Vorteile liegen in der einfachen Implementierung und der hohen Effizienz. Der Nachteil besteht darin, dass es zu Zirkelverweisen kommen kann, die zu einem Speicherüberlauf führen.
3. Mark-Clear-Methode
Mark- Die Clearing-Methode ist unterteilt in Zwei Stufen: „Markieren“ und „Löschen“ entsprechend dem Namen. Die Grundidee ist:Markieren Sie zunächst alle überlebenden Objekte. Nach Abschluss der Markierung werden alle markierten Objekte einheitlich gelöscht. Wie lässt sich also feststellen, ob ein Gegenstand recycelt werden kann? Während der GC beginnt die Durchquerung bei einer Reihe von GC-Roots-Wurzelknoten. Der während der Durchquerung zurückgelegte Pfad wird als Referenzkette bezeichnet. Wenn ein Objekt keine Referenzkette hat, die sich auf GC-Roots bezieht, ist das Objekt nicht verfügbar und wird es sein Als verfügbar eingestuft wird dieser Algorithmus auch als Root-Suchalgorithmus bezeichnet . Welche Objekte können also zu GC Roots-Objekten werden? In der Java-Sprache umfasst das Objekt der GC ROOTS die folgenden 4 Typen: Zitierte Variablen im Stapel der virtuellen Maschine Das Objekt statischer Attribute im Methodenbereich
Objekte, auf die durch Konstanten im Methodenbereich verwiesen wird
Von JNI (native Methode) referenziertes Objekt im lokalen Methodenstapel
Das Algorithmusdiagramm der Mark-and-Clear-Methode lautet wie folgt:
Hinweis: Das Bild des GC-Recycling-Algorithmus stammt aus einem Internetnutzer-Artikel (hier klicken). Der Inhalt des Internetnutzer-Bildes stimmt ebenfalls mit dem Originalwerk überein, die Farbe ist jedoch unterschiedlich.
4. Kopiermethode der neuen Generation
Die Grundidee der Kopiermethode ist: Teilen Sie die Speicher in 2 Blöcke gleicher Größe, von denen jeweils nur einer verwendet wird. Während der GC werden jedes Mal alle überlebenden Objekte in einen anderen Bereich kopiert und dann der Speicher bereinigt .
Dies sind alles Referenzobjekte im Methodenbereich und im Stapel. Die Vorteile der Kopiermethode sind: einfache Implementierung, schnelles Recycling und keine Speicherfragmentierung. Da jedoch jeweils nur ein Block verwendet wird, ist die Speicherauslastung gering. Das schematische Diagramm des Replikationsalgorithmus lautet wie folgt:
Verwandte Empfehlungen:
JVM-Garbage-Collection-Algorithmus
Teilen Sie die Zusammenfassung des Java-Garbage-Collection-Mechanismus
Das obige ist der detaillierte Inhalt vonStudiennotizen zur JAVA-Virtual-Machine: Garbage-Collection-Methode im JVM-Speichermodell. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!