Wie erzwinge ich die Speicherbereinigung in Java?

225

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

Robert Columbia
quelle
30
Vielleicht wäre es hilfreich, Hintergrundinformationen zu liefern, warum Sie GC erzwingen müssen. In der Regel ist es in einer Sprache, in der Müll gesammelt wird, eine schlechte Praxis, den Kollektor explizit aufzurufen.
Justin Ethier
3
Eine bestimmte JVM kann mehrere Garbage Collection-Methoden bereitstellen, von denen jede ihre eigenen Vor- und Nachteile hat. Häufig kann eine bestimmte Situation vermieden werden, indem die JVM zum Startzeitpunkt einfach angedeutet wird. Bitte erläutern Sie das Szenario.
Thorbjørn Ravn Andersen
3
jmap -histo: live <pid> stackoverflow.com/questions/6418089/…
5
Hier ist ein Anwendungsfall zum Erzwingen der Speicherbereinigung: Ich habe einen Server mit einem 30-GB-Heap, von dem normalerweise ~ 12 GB verwendet werden (~ 5 Millionen Objekte). Alle 5 Minuten verbringt der Server ungefähr eine Minute damit, eine komplexe Aufgabe auszuführen, bei der ungefähr 35 Millionen zusätzliche Objekte verwendet werden. Ein vollständiger GC wird mehrmals pro Stunde ausgelöst, immer während der komplexen Aufgabe, und friert die VM für 10 bis 15 Sekunden ein. Ich würde gerne den vollständigen GC zwingen, zu einem Zeitpunkt ausgeführt zu werden, an dem die komplexe Aufgabe nicht ausgeführt wird. es würde dann eher 5 Millionen lebende Objekte als 40 Millionen jonglieren.
Steve
3
@JustinEthier Es gibt einen ziemlich offensichtlichen Fall, in dem Sie den GC erzwingen möchten. Hierbei handelt es sich um einen Unit-Test für jedes Verhalten, das die Hierarchie des Typs java.lang.ref.Reference betrifft.
Elias Vasylenko

Antworten:

169

Am besten rufen Sie an, System.gc()was lediglich ein Hinweis für den Garbage Collector ist, dass er eine Sammlung durchführen soll. Es gibt jedoch keine Möglichkeit, eine sofortige Sammlung zu erzwingen, da der Garbage Collector nicht deterministisch ist.

Andrew Hare
quelle
28
Es sollte geben. non-deterministic == trouble
Pacerier
7
Ein Garbage Collector ist möglicherweise nicht deterministisch und bietet dennoch die Möglichkeit, eine sofortige Sammlung zu erzwingen. Beispielsweise ist der .NET-Kollektor normalerweise nicht deterministisch, aber ein Aufruf von GC.Collect () erzwingt die Ausführung. Es ist nur so, dass Java diese Funktion nicht verfügbar macht.
Petr Hudeček
2
Nach meiner Erfahrung ruft diese Methode immer den Garbage Collector auf. Dies geschieht so regelmäßig, dass meine Diagramme der Speichernutzung im Verhältnis zur Anzahl der deklarierten Objekte immer streng linear sind (Berücksichtigung des Auffüllens usw.).
Jim Pivarski
Ich dachte, dass der Garbage Collector automatisch ausgeführt wird, wenn neue Objekte
zugewiesen
@ PetrHudeček In realen Anwendungen sammelt .NET GC.Collect()nicht. In Java gc()tut.
Ajeh
53

Die jlibs-Bibliothek verfügt über eine gute Dienstprogrammklasse für die Speicherbereinigung . Mit WeakReference- Objekten können Sie die Speicherbereinigung mit einem kleinen Trick 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();
     }
   }
Täuschungen
quelle
1
Dieser Code ist fehlerhaft, weil ein schwacher Ref gelöscht wird, sobald sein Referent schwach erreichbar ist, bevor er aus dem Speicher gelöscht wird.
Marko Topolnik
1
Möglicherweise verbinden Sie die Bedeutung von "GC wurde ausgeführt" mit "Speicher wurde zurückgefordert". Das Objekt lebt weiter und ist noch nicht einmal finalisiert, aber Sie können nicht mehr über die schwache Referenz darauf zugreifen. Ein etwas besserer Weg wäre, a PhantomReferencemit a zu verwenden, ReferenceQueueund dann würden Sie nach der Finalisierung, aber noch vor der Bereinigung benachrichtigt. Selbst wenn Sie erfolgreich feststellen würden, dass der Speicher für dieses Objekt zurückgefordert wurde, würde dies in einem Generations-GC wie dem von HotSpot immer noch sehr wenig bedeuten. Normalerweise würde es mit der Säuberung der jungen Generation zusammenfallen.
Marko Topolnik
20
OP hat eine Lösung zum "Erzwingen der Speicherbereinigung" angefordert, und Sie haben behauptet, diese bereitzustellen. Das Ausführen des GC-Subsystems ist eine Sache, das Sammeln von Müll eine andere. Das von Ihnen bereitgestellte Codebeispiel hat eindeutig die Absicht, sicherzustellen, dass Müll gesammelt wurde. Da es sich um eine sehr alte Frage handelt, geht es offensichtlich nicht um die Wünsche von OP, sondern um den Nutzen für die breite Öffentlichkeit. Niemand ist daran interessiert, "das GC-Subsystem zum Ausführen zu zwingen", ohne dass Müll gesammelt wird. Tatsächlich wollen die Leute normalerweise eine Garantie dafür, dass der gesamte Müll gesammelt wurde.
Marko Topolnik
4
Sie haben es wahrscheinlich nicht mit der Effizienz von verglichen System.gc(); System.gc();, aber es wäre sicher interessant zu wissen, ob es jemals besser funktioniert hat. In der Tat System.gc()würde es ausreichen , nur zu drucken, wie oft es aufgerufen wurde . Die Chance, jemals 2 zu erreichen, ist ziemlich gering.
Marko Topolnik
3
@MarkoTopolnik: 'Niemand ist daran interessiert, "das GC-Subsystem zum Laufen zu zwingen", ohne dass Müll gesammelt wird' .... Eigentlich war ich heute nur an diesem Verhalten interessiert. Ich bin dankbar, dass diese Antwort vorhanden war. Mein Ziel war es, das Rotationsverhalten der GC-Protokollbehandlung zu überprüfen und das Format der GC-Ausgabe zu ermitteln. Dieser kleine Trick hat mir geholfen, die GC-Protokolle schnell zu füllen.
erik.weathers
49

Der beste (wenn nicht nur) Weg, einen GC zu erzwingen, wäre das Schreiben einer benutzerdefinierten JVM. Ich glaube, die Garbage Collectors sind steckbar, sodass Sie wahrscheinlich nur eine der verfügbaren Implementierungen auswählen und optimieren können.

Hinweis: Dies ist keine einfache Antwort.

Mainguy
quelle
40
+1 für lulz. Nichts macht frustrierendes Debuggen besser als jemand mit Sinn für Humor. anders als eine tatsächlich brauchbare Antwort.
Jsh
25

JA, es ist fast möglich zu erzwingen, dass Sie Methoden in derselben Reihenfolge aufrufen müssen, und gleichzeitig sind dies:

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

Selbst wenn es sich nur um ein Objekt handelt, um die Verwendung dieser beiden Methoden gleichzeitig zu bereinigen, wird der Garbage Collector gezwungen, die finalise()Methode des nicht erreichbaren Objekts zu verwenden, um den zugewiesenen Speicher freizugeben und die Anweisungen der finalize()Methode auszuführen.

JEDOCH es eine schreckliche Praxis ist die Garbage Collector zu verwenden , da die Verwendung von ihm könnte eine Überlast auf die Software einzuführen, die noch schlimmer als auf dem Speicher sein können, hat der Garbage Collector seinen eigenen Thread , die nicht möglich ist , zu steuern und je nach Der vom GC verwendete Algorithmus kann mehr Zeit in Anspruch nehmen und wird als sehr ineffizient angesehen. Sie sollten Ihre Software mit Hilfe des GC überprüfen, wenn er am schlimmsten ist, da er definitiv kaputt ist. Eine gute Lösung darf nicht vom GC abhängen.

HINWEIS: Nur um zu bedenken, dass dies nur funktioniert, wenn bei der Finalisierungsmethode keine Neuzuweisung des Objekts erfolgt. In diesem Fall bleibt das Objekt am Leben und es wird eine technisch mögliche Auferstehung auftreten.

Legramira
quelle
10
NEIN , selbst diese beiden Befehle erzwingen KEINE Speicherbereinigung. Wie bereits von anderen erwähnt, gc()ist dies nur ein Hinweis zum Ausführen einer Garbage Collection. runFinalizers()führt Finalizer nur für Objekte aus, "die als verworfen befunden wurden". Wenn der GC nicht tatsächlich ausgeführt wurde, gibt es möglicherweise keine solchen Objekte ...
Steffen Heil
Außerdem ist System.runFinalization () keine Garantie dafür, dass etwas ausgeführt wird. Es ist möglich, dass überhaupt nichts passiert. Es ist ein Vorschlag - von Javadoc: "Der Aufruf dieser Methode legt nahe, dass die Java Virtual Machine Anstrengungen unternimmt, um die Finalisierungsmethoden von Objekten auszuführen, die verworfen wurden, deren Finalisierungsmethoden jedoch noch nicht ausgeführt wurden "
kaan
21

In der Dokumentation zu OutOfMemoryError wird angegeben , dass es nicht ausgelöst wird, es sei denn, die VM konnte nach einer vollständigen Speicherbereinigung keinen Speicher zurückfordern. Wenn Sie also weiterhin Speicher zuweisen, bis Sie den Fehler erhalten, haben Sie bereits eine vollständige Speicherbereinigung erzwungen.

Vermutlich war die Frage, die Sie wirklich stellen wollten, "Wie kann ich die Erinnerung zurückgewinnen, von der ich denke, dass ich sie durch Speicherbereinigung zurückgewinnen sollte?"

Pete Kirkham
quelle
18

So fordern Sie GC manuell an (nicht von System.gc ()):

  1. Gehen Sie zum Ordner: bin im JDK, z. B.-C: \ Programme \ Java \ jdk1.6.0_31 \ bin
  2. Öffnen Sie jconsole.exe
  3. Stellen Sie eine Verbindung zum gewünschten lokalen Prozess her.
  4. Gehen Sie zur Registerkarte Speicher und klicken Sie auf GC ausführen.
Pinkesh Sharma
quelle
3
Oppsss irreführend. Bitte bewegen Sie den Mauszeiger über die Schaltfläche "GC durchführen". Sie können JVM auffordern, GC durchzuführen, aber niemals erzwingen.
Kumaran
@PinkeshSharma, wird dadurch nicht erzwingen . Es ist eine bloße Anfrage, die wahrscheinlich völlig ignoriert werden könnte.
Pacerier
@ Pacerier In einer idealen Welt ja .. aber wenn Sie dies tun, werden Sie sehen, dass es eine Zunahme des Gedächtnisses sofort gibt ...
Pinkesh Sharma
11

.gc ist ein Kandidat für die Eliminierung in zukünftigen Versionen - ein Sun Engineer hat einmal kommentiert, dass vielleicht weniger als zwanzig Menschen auf der Welt tatsächlich wissen, wie man .gc () verwendet - ich habe letzte Nacht einige Stunden an einer zentralen / kritischen Stelle gearbeitet Datenstruktur unter Verwendung von SecureRandom-generierten Daten, bei etwas mehr als 40.000 Objekten würde die VM langsamer werden, als ob ihr die Zeiger ausgegangen wären. Offensichtlich verschluckte es sich an 16-Bit-Zeigertabellen und zeigte ein klassisches Verhalten bei "fehlerhaften Maschinen".

Ich versuchte -Xms und so weiter, drehte weiter, bis es ungefähr 57, xxx etwas werden würde. Dann würde es gc von etwa 57.127 auf 57.128 nach einem gc () laufen lassen - ungefähr so ​​schnell wie das Code-Bloat im Camp Easy Money.

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

Nicholas Jordan
quelle
1
Ich habe so etwas, viele Objekte im Speicher, die ich nicht freigeben kann. Wenn die OutOfMemory-Ausnahme ausgelöst wird, möchte ich GC zwingen, zu testen, ob ein Erstellungsprozess für unendliche Objekte vorliegt oder ob diese Objekte von meinem System verwendet werden.
Klingt so, als würden Sie an dem gleichen Problem arbeiten, das ich bin. Bitte erklären Sie: "Unendliche Objekterstellung" ... gutes Forschungsprojekt, vielleicht können Sie hier eine Frage oder etwas in einem Java-Bereich posten (ich bin hier neu und nicht Ich habe gestern versucht, file.dat zu machen, als der Compiler "zu viel Code" auf 40.000 base36 BigIntegers beschwerte, die als statische letzte Zeichenfolge codiert sind. [] Ich werde meinen Hals stecken Hier und spekulieren Sie, dass die gesamte JVM auf 16-Bit-Zeiger beschränkt ist. Ich wette, wir müssen aggressiv null sein und von der Festplatte einlesen ...
Nicholas Jordan
Wirklich, ich verstehe dich nicht. Aber um klar zu sein über "Unendliche Objekterstellung", meinte ich, dass es in meinem großen System einen Teil des Codes gibt, der Objekte erstellt, die im Speicher verarbeitet und lebendig sind. Ich konnte diesen Teil des Codes eigentlich nicht bekommen, nur eine Geste !!
5
Unsinn! Es gibt einen offensichtlichen Fall, in dem es verwendet werden sollte: Testen von Code, der schwache Referenzen verwendet, damit wir sicherstellen können, dass das Verhalten korrekt ist, wenn schwache Referenzen gelöscht werden.
Elias Vasylenko
6

Die JVM-Spezifikation sagt nichts Spezifisches über die Speicherbereinigung aus. Aus diesem Grund steht es den Anbietern frei, GC auf ihre Weise zu implementieren.

Diese Unbestimmtheit führt also zu Unsicherheit im Verhalten der Speicherbereinigung. Sie sollten Ihre JVM-Details überprüfen, um Informationen zu den Garbage Collection-Ansätzen / -Algorithmen zu erhalten. Es gibt auch Optionen zum Anpassen des Verhaltens.

rai.skumar
quelle
4

Wenn Sie die Speicherbereinigung erzwingen müssen, sollten Sie möglicherweise überlegen, wie Sie Ressourcen verwalten. Erstellen Sie große Objekte, die im Speicher verbleiben? Erstellen Sie große Objekte (z. B. Grafikklassen) mit einer DisposableSchnittstelle und rufen Sie nicht auf, dispose()wenn Sie damit fertig sind? Erklären Sie etwas auf Klassenebene, das Sie nur innerhalb einer einzigen Methode benötigen?

Bob Kaufman
quelle
2

Es wäre besser, wenn Sie den Grund beschreiben würden, warum Sie eine Speicherbereinigung benötigen. Wenn Sie SWT verwenden, können Sie Ressourcen wie Imageund Fontzur Speicherfreigabe bereitstellen. Zum Beispiel:

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

Es gibt auch Tools zum Ermitteln nicht verfügbarer Ressourcen.

Paul Lammertsma
quelle
Was ist, wenn es keine Entsorgungsmethode gibt?
ArifMustafa
1
Völlig unabhängig von der Frage! Nein, ich benutze kein SWT. Ich rufe eine JNI-Methode auf, die ein .NET-Fenster über eine native Delphi-Ebene öffnet. Ich habe auch einen FORTRAN-Rechenkern, der Daten über eine native C ++ - Schicht empfängt. Was hat das mit irgendetwas zu tun? Kann ich einen GC erzwingen oder nicht? Nein? :-(
Mostafa Zeinali
0

Wenn Ihnen der Speicher ausgeht und OutOfMemoryExceptionSie einen Speicherplatz erhalten, können Sie versuchen, den für Java verfügbaren Heap-Speicherplatz zu erhöhen, indem Sie Ihr Programm mit java -Xms128m -Xmx512mstatt nur starten java. Dies gibt Ihnen eine anfängliche Heap-Größe von 128 MB und ein Maximum von 512 MB, was weit mehr als die Standardgröße von 32 MB / 128 MB ist.

Viktor Dahl
quelle
Die Standardspeichereinstellungen sindjava -Xms512M -Xmx1024M
ThePyroEagle
0

Eine andere Möglichkeit besteht darin, keine neuen Objekte zu erstellen.

Objektpooling ist weg, um den GC-Bedarf in Java zu verringern.

Das Objekt-Pooling ist im Allgemeinen nicht schneller als die Objekterstellung (insbesondere für Lightweight-Objekte), aber schneller als die Garbage Collection. Wenn Sie 10.000 Objekte erstellt haben und jedes Objekt 16 Byte groß war. Das sind 160.000 Bytes, die GC zurückfordern muss. Wenn Sie jedoch nicht alle 10.000 gleichzeitig benötigen, können Sie einen Pool zum Recyceln / Wiederverwenden der Objekte erstellen, sodass keine neuen Objekte erstellt werden müssen und keine alten Objekte mehr analysiert werden müssen.

So etwas (ungetestet). Und wenn Sie möchten, dass es threadsicher 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) { }

}
Aaron T. Harris
quelle
0

Unter OracleJDK 10 mit G1 GC führt ein einziger 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, selbst wenn System.gc()sie mehrmals in einer Schleife aufgerufen wird. Damit GC die Young Collection bereinigt, müssen Sie in einer Schleife (z . B. new byte[1024]) ohne Aufruf zuweisen System.gc(). Wenn Sie System.gc()aus irgendeinem Grund anrufen, kann GC die Young Collection nicht bereinigen.

Nathan
quelle
0

Wirklich, ich verstehe dich nicht. Aber um klar zu sein über "Unendliche Objekterstellung", meinte ich, dass es in meinem großen System einen Teil des Codes gibt, der Objekte erstellt, die im Speicher verarbeitet und lebendig sind. Ich konnte diesen Teil des Codes eigentlich nicht bekommen, nur eine Geste !!

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

  1. Ich konnte diesen Code eigentlich nicht bekommen

Richtig, es gibt kein tatsächliches JVM - dies ist nur eine Spezifikation, eine Menge Informatik, die ein gewünschtes Verhalten beschreibt ... Ich habe mich kürzlich mit der Initialisierung von Java-Objekten aus nativem Code befasst. Um das zu bekommen, was Sie wollen, müssen Sie nur das tun, was als aggressives Nullen bezeichnet wird. Die Fehler, wenn sie falsch gemacht werden, sind so schlimm, dass wir uns auf den ursprünglichen Umfang der Frage beschränken müssen:

  1. Ein Teil des Codes in meinem großen System erstellt Objekte

Bei den meisten Postern hier wird davon ausgegangen, dass Sie an einer Schnittstelle arbeiten. In diesem Fall müssten wir prüfen, ob Ihnen jeweils das gesamte Objekt oder ein Objekt übergeben wird.

Wenn Sie kein Objekt mehr benötigen, können Sie dem Objekt null zuweisen. Wenn Sie es jedoch falsch verstehen, wird eine Nullzeigerausnahme generiert. Ich wette, Sie können eine bessere Arbeit erzielen, wenn Sie NIO verwenden

Jedes Mal, wenn Sie, ich oder jemand anderes sagt: " Bitte, ich brauche das fürchterlich. " Es ist fast ein universeller Vorläufer für die fast vollständige Zerstörung dessen, woran Sie arbeiten möchten tatsächlich verwendeter Code und zeigen Sie uns Ihre Frage.

Sei nicht frustriert. Oft führt dies dazu, dass Ihre Datenbank ein Paket verwendet, das irgendwo gekauft wurde, und das ursprüngliche Design nicht für massive Datenstrukturen optimiert ist.

Das ist sehr häufig.

Nicholas Jordan
quelle
-1

Zu Ihrer Information

Der Methodenaufruf System.runFinalizersOnExit (true) garantiert, dass Finalizer-Methoden aufgerufen werden, bevor Java heruntergefahren wird. Diese Methode ist jedoch von Natur aus unsicher und veraltet. Eine Alternative besteht darin, mit der Methode Runtime.addShutdownHook "Shutdown Hooks" hinzuzufügen.

Masarrat Siddiqui

Masarrat Siddiqui
quelle
Der Fehler bei Shutdown-Haken ist, dass sie selten tatsächlich funktionieren. Das erzwungene Beenden funktioniert nicht, der Exit-Code ungleich Null funktioniert nicht, und manchmal führt die (offizielle) JVM sie einfach nicht aus, solange Sie sie zum Ausführen benötigen.
ThePyroEagle
-1

Es gibt eine indirekte Möglichkeit, den Garbage Collector zu erzwingen. Sie müssen den Heap nur mit temporären Objekten füllen, bis der Garbage Collector ausgeführt wird. Ich habe eine Klasse erstellt, die den Garbage Collector auf diese Weise zwingt:

class GarbageCollectorManager {

    private static boolean collectionWasForced;
    private static int refCounter = 0;

    public GarbageCollectorManager() {
        refCounter++;
    }

    @Override
    protected void finalize() {
        try {
            collectionWasForced = true;
            refCounter--;
            super.finalize();   
        } catch (Throwable ex) {
            Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int forceGarbageCollection() {
        final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
        int iterationsUntilCollected = 0;
        collectionWasForced = false;

        if (refCounter < 2) 
            new GarbageCollectorManager();

        while (!collectionWasForced) {
            iterationsUntilCollected++;
            int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
            arr = null;
        }

        return iterationsUntilCollected;
    }

}

Verwendung:

GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();

Ich weiß nicht , wie viel diese Methode ist nützlich, weil es Haufen ständig füllt, aber wenn Sie unternehmenskritische Anwendung, die MUST GC zwingen - wenn dies kann die Java tragbare Weg zu GC zu erzwingen.

Agnius Vasiliauskas
quelle
Was ist "final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;"?
Koray Tugay
Array-Größe - Wie viele temporäre Objekte (Ints) werden generiert, damit GC funktioniert.
Agnius Vasiliauskas
Ist das gültig: "_" in einer ganzen Zahl?
Koray Tugay
1
Ja, Unterstriche in numerischen Literalen sind ab Java SE 7 gültig. Dies ist beispielsweise als Tausendertrennzeichen in Ganzzahl wie in diesem Fall nützlich.
Agnius Vasiliauskas
3
Sie sollten solchen Code niemals in einem Produktionssystem ausführen. Während dieser Code in einem Thread ausgeführt wird, kann jeder andere Thread auch eine OutOfMemoryException erhalten, wobei die Absicht, dies überhaupt aufzurufen, vollständig rückgängig gemacht wird ....
Steffen Heil
-1

Ich möchte hier etwas hinzufügen. Bitte beachten Sie, dass Java nicht auf einer virtuellen Maschine und nicht auf einer tatsächlichen Maschine ausgeführt wird. Die virtuelle Maschine hat ihre eigene Art der Kommunikation mit der Maschine. Es kann von System zu System variieren. Wenn wir jetzt den GC aufrufen, bitten wir die virtuelle Maschine von Java, den Garbage Collector aufzurufen.

Da sich der Garbage Collector in der virtuellen Maschine befindet, können wir ihn nicht zwingen, dort und dann eine Bereinigung durchzuführen. Vielmehr stellen wir unsere Anfrage beim Garbage Collector in die Warteschlange. Dies hängt von der virtuellen Maschine ab. Nach einer bestimmten Zeit (dies kann sich von System zu System ändern, im Allgemeinen, wenn der der JVM zugewiesene Schwellenwertspeicher voll ist) gibt die tatsächliche Maschine den Speicherplatz frei. : D.

Saubhagya Ranjan Das
quelle
Der erste Satz des zweiten Absatzes ist keine Folge .
Marquis von Lorne
-1

Der folgende Code stammt aus der Methode assertGC (...). Es versucht, den nichtdeterministischen Garbage Collector zum Sammeln zu zwingen.

   List<byte[]> alloc = new ArrayList<byte[]>();
   int size = 100000;
   for (int i = 0; i < 50; i++) {
        if (ref.get() == null) {
             // Test succeeded! Week referenced object has been cleared by gc.
             return;
        }
        try {
             System.gc();
        } catch (OutOfMemoryError error) {
             // OK
        }
        try {
             System.runFinalization();
        } catch (OutOfMemoryError error) {
             // OK
        }

        // Approach the jvm maximal allocatable memory threshold
        try {
             // Allocates memory.
             alloc.add(new byte[size]);

             // The amount of allocated memory is increased for the next iteration.
             size = (int)(((double)size) * 1.3);
        } catch (OutOfMemoryError error) {
             // The amount of allocated memory is decreased for the next iteration.
             size = size / 2;
        }

        try {
             if (i % 3 == 0) Thread.sleep(321);
        } catch (InterruptedException t) {
             // ignore
        }
   }

   // Test failed! 

   // Free resources required for testing
   alloc = null;

   // Try to find out who holds the reference.
   String str = null;
   try {
        str = findRefsFromRoot(ref.get(), rootsHint);
   } catch (Exception e) {
        throw new AssertionFailedErrorException(e);
   } catch (OutOfMemoryError err) {
        // OK
   }
   fail(text + ":\n" + str);

Quelle (aus Gründen der Übersichtlichkeit habe ich einige Kommentare hinzugefügt): NbTestCase-Beispiel

H. Hess
quelle
-1

Sie können versuchen, Runtime.getRuntime().gc()die Dienstprogrammmethode zu verwenden oder zu verwenden. System.gc()Hinweis: Diese Methoden gewährleisten keine GC. Und ihr Umfang sollte auf JVM beschränkt sein, anstatt sie programmgesteuert in Ihrer Anwendung zu behandeln.

Nabster
quelle
2
Wie in den anderen Antworten erläutert, erzwingen diese Methoden keinen (vollständigen) Speicherbereinigungslauf.
Flow
-2

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

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