it-swarm.com.de

Wie erzwingen Sie die Garbage Collection in Java?

Ist es möglich, die Garbage Collection in Java zu erzwingen, auch wenn dies schwierig ist? Ich kenne System.gc(); und Runtime.gc();, aber sie schlagen nur vor, GC zu machen. Wie kann ich GC erzwingen?

192
user179172

Am besten rufen Sie System.gc() auf. Dies ist lediglich ein Hinweis auf den Garbage Collector, dass Sie eine Sammlung durchführen möchten. Es gibt keine Möglichkeit zu force und zur sofortigen Sammlung, obwohl der Garbage Collection-Speicher nicht deterministisch ist.

149
Andrew Hare

Die Bibliothek " jlibs" verfügt über eine gute Dienstprogrammklasse für die Garbage Collection . Mit WeakReference objects können Sie die Garbage Collection mithilfe eines kleinen Tricks erzwingen.

RuntimeUtil.gc () aus den jlibs:

   /**
    * This method guarantees that garbage collection is
    * done unlike <code>{@link System#gc()}</code>
    */
   public static void gc() {
     Object obj = new Object();
     WeakReference ref = new WeakReference<Object>(obj);
     obj = null;
     while(ref.get() != null) {
       System.gc();
     }
   }
50
shams

Die beste (wenn nicht nur) Möglichkeit, einen GC zu erzwingen, wäre das Erstellen einer benutzerdefinierten JVM. Ich glaube, die Müllsammler sind steckbar, so dass Sie wahrscheinlich nur eine der verfügbaren Implementierungen auswählen und optimieren können.

Hinweis: Dies ist KEINE einfache Antwort.

40
Mainguy

Verwenden der Java ™ Virtual Machine Tool-Schnittstelle (JVM TI) die Funktion

jvmtiError ForceGarbageCollection(jvmtiEnv* env)

wird "die VM zwingen, eine Speicherbereinigung durchzuführen". Die JVM-TI ist Teil der JavaTM-Plattform-Debuggerarchitektur (JPDA) .

38
trashgod

YESes ist fast möglich, dass Sie gezwungen sind, Methoden in derselben Reihenfolge aufzurufen, und gleichzeitig sind diese:

System.gc ();
System.runFinalization ();

selbst wenn es nur ein Objekt ist, das die Verwendung dieser beiden Methoden gleichzeitig bereinigt, zwingt der Garbage Collector zur Verwendung der finalise()-Methode eines nicht erreichbaren Objekts, wodurch der zugewiesene Speicher freigegeben wird und die in der finalize()-Methode angegebenen Anweisungen ausgeführt werden.

JEDOCHEs ist eine schreckliche Praxis, den Garbage Collector zu verwenden, da die Verwendung des Garbage Collection möglicherweise zu einer Überlastung der Software führt, die möglicherweise sogar noch schlimmer ist als der Speicher. Der Garbage Collection hat seinen eigenen Thread, der nicht der Fall ist Je nach Algorithmus, den der gc verwendet, plus zu steuern, könnte dies mehr Zeit in Anspruch nehmen und ist sehr ineffizient. Sie sollten Ihre Software überprüfen, wenn es mit Hilfe des gc am schlimmsten ist, da sie definitiv pleite ist gc.

HINWEIS: Nur um zu wissen, dass dies nur funktioniert, wenn in der finalize-Methode keine Neuzuweisung des Objekts erfolgt. Wenn dies geschieht, wird das Objekt am Leben bleiben und eine Wiederbelebung haben, die technisch möglich ist.

24
legramira

In der Dokumentation für OutOfMemoryError wird erklärt, dass es nicht ausgelöst wird, es sei denn, VM konnte den Speicher nach einer vollständigen Speicherbereinigung nicht abrufen. Wenn Sie also weiterhin Speicher zuweisen, bis Sie den Fehler erhalten, haben Sie bereits eine vollständige Garbage Collection erzwungen. 

Vermutlich war die Frage, die Sie wirklich stellen wollten, die Frage "Wie kann ich die Erinnerung zurückgewinnen, die ich meiner Meinung nach durch die Müllsammlung zurückfordern sollte?"

18
Pete Kirkham

Manuelles Anfordern von GC (nicht von System.gc ()): 

  1. Gehe zu: bin Ordner in JDK zB-C:\Programme\Java\jdk1.6.0_31\bin
  2. Öffnen Sie die Datei jconsole.exe
  3. Verbinden Sie sich mit dem gewünschten lokalen Prozess.
  4. Wechseln Sie zur Registerkarte Speicher und klicken Sie auf GC ausführen.
15
Pinkesh Sharma

.gc ist ein Kandidat für die Beseitigung in zukünftigen Versionen. Ein Sun Engineer hat einmal gesagt, dass vielleicht weniger als zwanzig Menschen auf der Welt tatsächlich wissen, wie .gc () zu verwenden ist Datenstruktur mithilfe von SecureRandom generierten Daten. Bei etwas mehr als 40.000 Objekten würde der VM langsamer werden, als hätte er keine Zeiger mehr. Es war eindeutig, dass es an 16-Bit-Zeigertabellen erstickte und ein klassisches Verhalten "ausfallender Maschinen" zeigte.

Ich habe -Xms und so weiter ausprobiert und etwas herumgedreht, bis es auf etwa 57, xxx etwas laufen würde. Dann würde es gc von etwa 57.127 bis 57.128 nach einem gc () laufen - bei etwa dem Tempo des Aufblähens im Camp Easy Money.

Ihr Entwurf muss grundlegend überarbeitet werden, wahrscheinlich mit einem Schiebefenster. 

11
Nicholas Jordan

Sie können einen GC über die Befehlszeile auslösen. Dies ist nützlich für Batch/Crontab:

jdk1.7.0/bin/jcmd <pid> GC.run

Sehen :

8
guest

Die JVM-Spezifikation sagt nichts über die Garbage Collection aus. Daher können Anbieter GC auf ihre Art und Weise implementieren.

Diese Unbestimmtheit führt also zu Unsicherheiten im Müllsammelverhalten. Sie sollten Ihre JVM-Details überprüfen, um mehr über die Ansammlung/Algorithmen der Garbage Collection zu erfahren. Es gibt auch Optionen zum Anpassen des Verhaltens.

6
rai.skumar

Wenn Sie die Speicherbereinigung erzwingen möchten, sollten Sie möglicherweise überlegen, wie Sie Ressourcen verwalten. Erstellen Sie große Objekte, die im Speicher bestehen bleiben? Erstellen Sie große Objekte (z. B. Grafikklassen), die über eine Disposable-Schnittstelle verfügen und dispose() nicht aufrufen, wenn Sie damit fertig sind? Erklären Sie etwas auf Klassenebene, das Sie nur innerhalb einer einzigen Methode benötigen?

4
Bob Kaufman

Es wäre besser, wenn Sie den Grund beschreiben, warum Sie eine Müllsammlung benötigen. Wenn Sie SWT verwenden, können Sie Ressourcen wie Image und Font bereitstellen, um Speicher freizugeben. Zum Beispiel:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

Es gibt auch Tools zur Ermittlung nicht verfügbarer Ressourcen.

2
Paul Lammertsma

Verwenden Sie Runtime.getRuntime().gc() oder verwenden Sie die Dienstprogrammmethode System.gc().

1
nabster

Wenn Ihnen der Speicher ausgeht und Sie eine OutOfMemoryException erhalten, können Sie versuchen, den für Java verfügbaren Heap-Speicherplatz zu erhöhen, indem Sie Ihr Programm mit Java -Xms128m -Xmx512m statt nur mit Java starten. Dadurch erhalten Sie eine anfängliche Heap-Größe von 128 MB und maximal 512 MB, was weit über dem Standardwert von 32 MB/128 MB liegt.

0
Viktor Dahl

Wenn Sie JUnit und Spring verwenden, fügen Sie dies in jeder Testklasse hinzu:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
0
Aliuk

Eine weitere Option ist, keine neuen Objekte anzulegen.

Object Pooling ist weg, um den Bedarf an GC in Java zu reduzieren.

Das Objekt-Pooling ist im Allgemeinen nicht schneller als die Objekterstellung (insbesondere für Objekte mit geringer Größe), aber es ist schneller als die Garbage Collection. Wenn Sie 10.000 Objekte erstellt haben und jedes Objekt 16 Bytes hatte. Das sind 160.000 Bytes, die GC zurückfordern muss. Wenn Sie andererseits nicht alle 10.000 gleichzeitig benötigen, können Sie einen Pool erstellen, um die Objekte zu recyceln/wiederzuverwenden. Dadurch müssen keine neuen Objekte erstellt werden, und Sie müssen keine alten Objekte mehr GC-Objekte erstellen.

So etwas (ungetestet) . Und wenn Sie wollen, dass es Thread-sicher ist, können Sie die LinkedList gegen eine ConcurrentLinkedQueue austauschen.

public abstract class Pool<T> {
    private int mApproximateSize;
    private LinkedList<T> mPool = new LinkedList<>();

    public Pool(int approximateSize) {
        mApproximateSize = approximateSize;
    }

    public T attain() {
        T item = mPool.poll();
        if (item == null) {
            item = newInstance();
        }
        return item;
    }

    public void release(T item) {
        int approxSize = mPool.size(); // not guaranteed accurate
        if (approxSize < mApproximateSize) {
            recycle(item);
            mPool.add(item);
        } else if (approxSize > mApproximateSize) {
            decommission(mPool.poll());
        }
    }

    public abstract T newInstance();

    public abstract void recycle(T item);

    public void decommission(T item) { }

}
0
Aaron T Harris

(Leider kann ich das nicht als Kommentar hinzufügen, da ich nicht genügend Rufpunkte habe.)

Ich habe einmal bei einer Bildverarbeitungsfirma für einen Java-Job interviewt (obwohl ich keine/viel Java-Erfahrung hatte.)

Ihre Leidensgeschichte, die für mich interessant war, bestand darin, dass ihr Programm einen riesigen Puffer für das Image bereitstellte. Sobald sie mit dem Bild und der Erinnerung fertig waren, würden sie es respektieren. Sie wussten, dass sie den Speicher früher als später wirklich wiederherstellen mussten, und versuchten, einen expliziten Aufruf von Java gc () während einer ruhigen Zeit des Programms zu verwenden. Leider ist gc () nur ein Vorschlag zur Java-Laufzeit und hatte keine Auswirkungen.

Soweit ich mich erinnere, mussten sie den Speicher selbst recyceln.

0
Clem Wang

Bei OracleJDK 10 mit G1 GC führt ein einmaliger 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, auch wenn System.gc() in einer Schleife häufig aufgerufen wird. Damit GC die Young Collection bereinigen kann, müssen Sie die Schleife in einer Schleife zuweisen (z. B. new byte[1024]), ohne System.gc() aufzurufen. Der Aufruf von System.gc() aus irgendeinem Grund verhindert, dass GC die Young Collection aufräumt.

0
Nathan

Wirklich, ich verstehe dich nicht. Aber sein Klar über "unendliche Objekterstellung" Ich meinte, dass es ein Stück von .__ gibt. Code bei meinem großen System erstellen von Objekte, die sich in Erinnerung, ich konnte dieses Stück .__ nicht bekommen. Code eigentlich nur Geste !!

Das ist richtig, nur Geste. Sie haben so ziemlich die Standardantworten, die bereits von mehreren Postern gegeben wurden. Nehmen wir dies nacheinander:

  1. Ich konnte dieses Stück Code eigentlich nicht bekommen

Richtig, es gibt keine eigentliche jvm - das ist nur eine Spezifikation, eine Reihe von Informatikern, die ein gewünschtes Verhalten beschreiben ... Ich habe vor kurzem Java-Objekte aus nativem Code initialisiert. Um das zu bekommen, was Sie möchten, können Sie das tun, was als aggressives Nulling bezeichnet wird. Die Fehler, wenn sie falsch gemacht werden, sind so schlecht, dass wir uns auf den ursprünglichen Umfang der Frage beschränken müssen: 

  1. ein Stück Code in meinem großen Systemdo Erstellung von Objekten

Bei den meisten Postern hier wird davon ausgegangen, dass Sie sagen, dass Sie an einer Schnittstelle arbeiten. Wenn dies der Fall ist, müssen wir sehen, ob Ihnen jeweils das gesamte Objekt oder ein Element übergeben wird.

Wenn Sie ein Objekt nicht mehr benötigen, können Sie dem Objekt null zuweisen. Wenn Sie es falsch verstehen, wird eine Nullzeiger-Ausnahme generiert. Ich wette, Sie können bessere Arbeit erzielen, wenn Sie NIO verwenden

Jedes Mal, wenn Sie oder ich oder sonst jemand anders wird: " Bitte ich brauche das schrecklich. " Es ist fast ein universeller Vorläufer für eine nahezu vollständige Zerstörung dessen, woran Sie arbeiten wollen. Schreiben Sie uns einen kleinen Beispielcode. Bereinigen Sie daraus den tatsächlich verwendeten Code und zeigen Sie uns Ihre Frage.

Sei nicht frustriert. In der Regel verwendet das dba ein Paket, das irgendwo gekauft wurde, und das ursprüngliche Design ist nicht für massive Datenstrukturen optimiert. 

Das ist sehr verbreitet.

0
Nicholas Jordan