Heim  >  Artikel  >  Java  >  Vertiefendes Verständnis des Java-Garbage-Collection-Mechanismus und von Speicherlecks

Vertiefendes Verständnis des Java-Garbage-Collection-Mechanismus und von Speicherlecks

高洛峰
高洛峰Original
2017-01-17 15:38:211083Durchsuche

Vorwort

Ich habe eine Frage zu Segmentfault gesehen: Java verfügt über einen vollständigen GC-Mechanismus. Wird es in Java also Speicherlecks geben, und können Sie einen Fall von Speicherlecks angeben? Diese Fragenansicht gibt die vollständige Antwort auf diese Frage.

Einführung in den Garbage-Collection-Mechanismus

Während der Ausführung des Programms wird jedes Mal, wenn ein Objekt erstellt wird, eine bestimmte Menge Speicher zum Speichern von Objektdaten zugewiesen. Wenn Sie einfach weiterhin Speicher zuweisen, wird das Programm früher oder später mit dem Problem konfrontiert, dass nicht genügend Speicher vorhanden ist. Daher gibt es in jeder Sprache einen Speicherrecyclingmechanismus, um den Speicher abgelaufener Objekte freizugeben und sicherzustellen, dass der Speicher wiederverwendet werden kann.

Der Speicherrecyclingmechanismus kann entsprechend den unterschiedlichen Implementierungsrollen in zwei Typen unterteilt werden. Der eine besteht darin, dass der Programmierer den Speicher manuell freigibt (z. B. in der C-Sprache), und der andere ist der integrierte Speicherrecyclingmechanismus von In diesem Artikel wird beispielsweise der Java-Garbage-Collection-Mechanismus vorgestellt.

Javas Garbage-Collection-Mechanismus

In der Laufzeitumgebung des Programms stellt die Java Virtual Machine einen Garbage-Collection-Thread (GC, Carbage Collection) auf Systemebene bereit, der für die Wiederverwertung verlorener Referenzen verantwortlich ist . Der vom Objekt belegte Speicher. Die Voraussetzung für das Verständnis von GC besteht darin, einige Konzepte im Zusammenhang mit der Speicherbereinigung zu verstehen. Diese Konzepte werden im Folgenden einzeln vorgestellt.

Der Status von Objekten im JVM-Heap-Bereich

Instanzen von Java-Objekten werden im JVM-Heap-Bereich gespeichert. Für GC-Threads haben diese Objekte drei Zustände.

1. Erreichbarer Zustand: Wenn im Programm Variablenverweise vorhanden sind, befindet sich dieses Objekt in einem erreichbaren Zustand.

2. Wiederbelebbarer Zustand: Wenn keine Variablen im Programm auf dieses Objekt verweisen, wechselt das Objekt vom berührbaren Zustand in den wiederbelebbaren Zustand. Der CG-Thread bereitet sich darauf vor, die Finalize-Methode dieses Objekts zu einem bestimmten Zeitpunkt aufzurufen (die Finalize-Methode erbt das Unterobjekt oder schreibt es neu). Der Code in der Finalize-Methode konvertiert das Objekt möglicherweise in einen berührbaren Zustand in einen unantastbaren Zustand umgewandelt.

3. Nicht erreichbarer Zustand: Nur wenn sich das Objekt in einem nicht erreichbaren Zustand befindet, kann der GC-Thread den Speicher dieses Objekts zurückfordern.

Vertiefendes Verständnis des Java-Garbage-Collection-Mechanismus und von Speicherlecks

Um Objekte korrekt freizugeben, muss GC den Betriebsstatus jedes Objekts überwachen, einschließlich Objektanwendung, Referenz, Referenz, Zuweisung usw. GC muss alles überwachen. Unabhängig davon, ob sich ein Objekt in einem der oben genannten Zustände befindet, weiß der GC dies.

Wie oben erwähnt, führt der GC-Thread zu einem bestimmten Zeitpunkt die Finalize-Methode des wiederbelebbaren Zustandsobjekts aus. Wann wird sie also ausgeführt? Da verschiedene JVM-Implementierer möglicherweise unterschiedliche Algorithmen zum Verwalten von GC verwenden, können Entwickler den Zeitpunkt verschiedener Vorgänge (einschließlich der Erkennung des Objektstatus, der Freigabe von Objektspeicher und des Aufrufs der Finalize-Methode des Objekts) durch den GC-Thread zu keinem Zeitpunkt vorhersagen. Obwohl der GC-Thread über die Funktionen System.gc() und Runtime.gc() so schnell wie möglich daran erinnert werden kann, Garbage-Collection-Vorgänge durchzuführen, gibt es keine Garantie dafür, dass der GC-Thread die entsprechenden Recyclingvorgänge sofort ausführt.

Speicherverlust

Speicherverlust bezieht sich auf das Versagen des Programms, Speicher freizugeben, der aufgrund eines falschen Designs nicht mehr verwendet wird, was zu einer Verschwendung von Ressourcen führt. GC bereinigt automatisch den Speicher, der von Objekten belegt wird, die Referenzen verloren haben. Wenn jedoch aufgrund eines Programmierfehlers immer auf einige Objekte verwiesen wird, kommt es zu einem Speicherverlust.

Zum Beispiel das folgende Beispiel. Ein Stapel wird mithilfe eines Arrays mit zwei Operationen implementiert: Push und Pop.

import com.sun.javafx.collections.ElementObservableListDecorator;
import com.sun.swing.internal.plaf.metal.resources.metal_sv;
 
import java.beans.ExceptionListener;
import java.util.EmptyStackException;
 
/**
 * Created by peng on 14-9-21.
 */
public class MyStack {
  private Object[] elements;
  private int Increment = 10;
  private int size = 0;
 
  public MyStack(int size) {
    elements = new Object[size];
  }
 
  //入栈
  public void push(Object o) {
    capacity();
    elements[size++] = o;
  }
 
  //出栈
  public Object pop() {
    if (size == 0)
      throw new EmptyStackException();
    return elements[--size];
  }
 
  //增加栈的容量
  private void capacity() {
    if (elements.length != size)
      return;
    Object[] newArray = new Object[elements.length + Increment];
    System.arraycopy(elements, 0, newArray, 0, size);
  }
 
  public static void main(String[] args) {
    MyStack stack = new MyStack(100);
    for (int i = 0; i < 100; i++)
      stack.push(new Integer(i));
    for (int i = 0; i < 100; i++) {
      System.out.println(stack.pop().toString());
    }
  }
}

Dieses Programm ist verfügbar und unterstützt gängige Push- und Pop-Vorgänge. Es gibt jedoch ein Problem, das nicht richtig behandelt wurde: Beim Öffnen des Stapels wird der Verweis auf das entfernte Element im Array nicht freigegeben. Dies führt dazu, dass das Programm einen Verweis auf dieses Objekt behält (auf dieses Objekt wird verwiesen). durch das Array). Der GC wird immer denken, dass dieses Objekt erreichbar ist, geschweige denn seinen Speicher freigeben. Dies ist ein typischer Fall eines Speicherverlusts. Als Antwort darauf lautet der geänderte Code:

//出栈
  public Object pop() {
    if (size == 0)
      throw new EmptyStackException();
    Object o = elements[--size];
    elements[size] = null;
    return o;
  }

Der obige Artikel über ein detailliertes Verständnis des Java-Garbage-Collection-Mechanismus und von Speicherlecks ist der gesamte vom Herausgeber geteilte Inhalt, den ich Ihnen hoffentlich vermitteln kann Eine Referenz. Ich hoffe auch, dass Sie die chinesische PHP-Website unterstützen.

Für ein tieferes Verständnis des Java-Garbage-Collection-Mechanismus und von Artikeln zu Speicherverlusten beachten Sie bitte die chinesische PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn