Jak wymusić zbieranie śmieci w Javie?

225

Czy można wymusić zbieranie śmieci w Javie, nawet jeśli jest to trudne? Znam System.gc();i Runtime.gc();ale tylko proponuję zrobić GC. Jak mogę zmusić GC?

Robert Columbia
źródło
30
Być może pomocne byłoby podanie tła, dlaczego musisz wymusić GC. Zwykle w języku odśmiecania śmieci złą praktyką jest jawne wywoływanie modułu pobierającego.
Justin Ethier,
3
Dana maszyna JVM może zapewniać kilka metod wyrzucania elementów bezużytecznych, z których każda ma swoje zalety i wady, a często danej sytuacji można uniknąć, po prostu wskazując maszynę JVM podczas uruchamiania. Proszę opracować scenariusz.
Thorbjørn Ravn Andersen
3
jmap -histo: live <pid> stackoverflow.com/questions/6418089/…
5
Oto przypadek użycia do wymuszenia wyrzucania elementów bezużytecznych: Mam serwer ze stertą 30 GB, z czego zwykle używane jest ~ 12 GB (~ 5 mln obiektów). Co 5 minut serwer poświęca około jednej minuty na wykonanie złożonego zadania, w którym wykorzystuje się około 35 mln dodatkowych obiektów. Pełny GC jest uruchamiany kilka razy na godzinę, niezmiennie podczas złożonego zadania i zamraża maszynę wirtualną na 10 do 15 sekund. Chciałbym wymusić uruchomienie pełnej GC w czasie, gdy złożone zadanie nie jest uruchomione; byłoby wtedy żonglowanie obiektami na żywo o wielkości 5 mln niż 40 mln.
Steve
3
@JustinEthier Jest jeden dość oczywisty przypadek, w którym możesz chcieć wymusić GC, którym jest testowanie jednostkowe dowolnego zachowania związanego z hierarchią typów java.lang.ref.Reference.
Elias Vasylenko

Odpowiedzi:

168

Najlepszą opcją jest wywołanie, System.gc()które jest po prostu wskazówką dla śmieciarza, że ​​ma on wykonywać kolekcję. Nie ma jednak sposobu na wymuszenie i natychmiastowe pobranie, ponieważ śmieciarz nie jest deterministyczny.

Andrew Hare
źródło
28
Powinno być. non-deterministic == trouble
Pacerier
7
Moduł wyrzucania elementów bezużytecznych może być niedeterministyczny i nadal oferuje sposób na wymuszenie natychmiastowego pobrania. Na przykład zwykle kolektor .NET jest niedeterministyczny, ale wywołanie GC.Collect () wymusza jego uruchomienie. Po prostu Java decyduje się nie ujawniać tej funkcji.
Petr Hudeček
2
Z mojego doświadczenia wynika, że ​​ta metoda zawsze wywołuje moduł wyrzucania elementów bezużytecznych. Robi to z wystarczającą regularnością, aby moje wykresy wykorzystania pamięci w porównaniu do liczby zadeklarowanych obiektów były zawsze ściśle liniowe (uwzględnianie wypełniania itp.).
Jim Pivarski,
Myślałem, że przydzielając nowe obiekty, a następnie nie odwołując się już do nich,
moduł śmieciowy
@ PetrHudeček W rzeczywistych aplikacjach .NET GC.Collect()nie zbiera. W Javie gc()robi.
ajeh
53

Biblioteka jlibs ma dobrą klasę użytkową do zbierania śmieci . Możesz wymusić wyrzucanie elementów bezużytecznych przy użyciu sprytnej sztuczki z obiektami WeakReference .

RuntimeUtil.gc () z 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();
     }
   }
oszustwa
źródło
1
Ten kod jest uszkodzony, ponieważ słaby odwołanie jest usuwane, gdy tylko jego odwołanie staje się słabo osiągalne, czyli przed usunięciem z pamięci.
Marko Topolnik
1
Być może rozumiesz znaczenie „GC uruchomił się” z „pamięć została odzyskana”. Obiekt żyje i nie jest jeszcze sfinalizowany, ale nie można uzyskać do niego dostępu przez słabe odniesienie. Nieco lepszym sposobem byłoby użycie PhantomReferencez, ReferenceQueuea następnie otrzymasz powiadomienie po zakończeniu, ale jeszcze przed czyszczeniem. Wreszcie, nawet jeśli uda się wykryć, że pamięć dla tego obiektu została odzyskana, nadal będzie to miało bardzo małe znaczenie w generacyjnej GC, takiej jak HotSpot. Zwykle zbiega się to w czasie z porządkiem młodego pokolenia.
Marko Topolnik
20
OP poprosił, a ty twierdziłeś, że dostarczyłeś rozwiązanie „wymuszające odśmiecanie”. Uruchamianie podsystemu GC to jedno, a właściwie zbieranie śmieci. Podany przez Ciebie przykład kodu ma wyraźnie na celu zagwarantowanie, że śmieci zostały zebrane. W każdym razie, to bardzo stare pytanie, oczywiście nie dotyczy życzeń OP, ale użyteczności dla ogółu społeczeństwa. Nikt nie jest zainteresowany „zmuszaniem podsystemu GC do działania” samodzielnie, bez zbierania śmieci. W rzeczywistości ludzie zwykle chcą gwarancji, że wszystkie śmieci zostały zebrane.
Marko Topolnik
4
Prawdopodobnie nie porównałeś go z wydajnością System.gc(); System.gc();, ale na pewno byłoby interesujące wiedzieć, czy kiedykolwiek zadziałałoby lepiej. W rzeczywistości wystarczy wydrukować, ile razy był wywoływany System.gc(). Szansa na osiągnięcie 2 jest dość niewielka.
Marko Topolnik,
3
@MarkoTopolnik: „Nikt nie jest zainteresowany„ zmuszeniem podsystemu GC do działania ”samodzielnie, bez zbierania śmieci”. Właściwie to właśnie dzisiaj byłem zainteresowany właśnie takim zachowaniem. Cieszę się, że ta odpowiedź była obecna. Moim celem było sprawdzenie zachowania rotacyjnego obsługi dziennika GC i uzyskanie formatu wyjścia GC. Ta mała sztuczka pomogła mi szybko wypełnić dzienniki GC.
erik.weathers
49

Najlepszym (jeśli nie tylko) sposobem wymuszenia GC byłoby napisanie niestandardowej maszyny JVM. Wierzę, że Garbage collectors można podłączyć, więc prawdopodobnie możesz po prostu wybrać jedną z dostępnych implementacji i dostosować ją.

Uwaga: To NIE jest łatwa odpowiedź.

Mainguy
źródło
40
+1 za lulz. nic nie sprawia, że ​​frustrujące debugowanie jest lepsze niż ktoś z poczuciem humoru. to znaczy inna niż faktycznie użyteczna odpowiedź.
jsh
25

TAK , prawie można zmusić cię do wywoływania metod w tej samej kolejności, a jednocześnie są to:

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

nawet jeśli jest to tylko jeden obiekt do wyczyszczenia przy użyciu tych dwóch metod jednocześnie, zmuś śmieciarz do użycia finalise()metody nieosiągalnego obiektu, zwalniając przydzieloną pamięć i wykonując czynności podane przez finalize()metodę.

JEDNAK to okropna praktyka korzystania z modułu wyrzucania elementów bezużytecznych, ponieważ użycie go może spowodować nadmierne obciążenie oprogramowania, które może być nawet gorsze niż w przypadku pamięci, moduł wyrzucający elementy ma własny wątek, którego nie można kontrolować plus w zależności od algorytm używany przez gc może zająć więcej czasu i jest uważany za bardzo nieefektywny, powinieneś sprawdzić swoje oprogramowanie, jeśli jest najgorsze z pomocą gc, ponieważ jest zdecydowanie zepsuty, dobre rozwiązanie nie może zależeć od gc.

UWAGA: aby pamiętać, będzie to działało tylko wtedy, gdy w metodzie finalizacji nie nastąpi zmiana przypisania obiektu, jeśli tak się stanie, obiekt pozostanie przy życiu i będzie miał zmartwychwstanie, które jest technicznie możliwe.

Legramira
źródło
10
NIE , nawet te dwa polecenia NIE wymuszą wyrzucania elementów bezużytecznych. Jak już wspomniano przez innych, gc()jest tylko wskazówką do uruchomienia śmiecia. runFinalizers()uruchamia finalizatory tylko na obiektach „uznanych za odrzucone”. Jeśli GC tak naprawdę nie uruchomił się, może nie być takich obiektów ...
Steffen Heil
również System.runFinalization () nie gwarantuje, że wszystko się uruchomi; możliwe, że nic się nie wydarzy. Jest to sugestia - od Javadoc: „ Wywołanie tej metody sugeruje, że wirtualna maszyna Java poświęci wysiłek na uruchomienie metod finalizacji obiektów, które zostały odrzucone, ale których metody finalizacji nie zostały jeszcze uruchomione
kaan
21

W dokumentacji OutOfMemoryError oświadcza, że ​​nie zostanie wyrzucony, dopóki maszyna wirtualna nie odzyska pamięci po pełnym wyrzucaniu elementów bezużytecznych. Więc jeśli będziesz nadal alokował pamięć, dopóki nie pojawi się błąd, już wymusiłeś pełne odśmiecanie.

Przypuszczalnie pytanie, które naprawdę chciałeś zadać, brzmiało: „jak mogę odzyskać pamięć, myślę, że powinienem ją odzyskać poprzez zbieranie śmieci?”.

Pete Kirkham
źródło
18

Aby ręcznie zażądać GC (nie z System.gc ()):

  1. Przejdź do: folderu bin w JDK np. -C: \ Program Files \ Java \ jdk1.6.0_31 \ bin
  2. Otwórz plik jconsole.exe
  3. Połącz się z żądanym procesem lokalnym.
  4. Przejdź do karty pamięci i kliknij przycisk Wykonaj GC.
Pinkesh Sharma
źródło
3
Oppsss wprowadza w błąd. Najedź myszką na przycisk „Wykonaj GC”. Możesz poprosić JVM o wykonanie GC, ale nigdy nie wymuszaj.
Kumaran
@PinkeshSharma, To nie wymusza . To zwykłe żądanie, które prawdopodobnie można całkowicie zignorować.
Pacerier
@Pacerier W idealnym świecie tak .. ale jeśli to zrobisz, natychmiast
zauważysz
11

.gc jest kandydatem do eliminacji w przyszłych wydaniach - inżynier Sun powiedział kiedyś, że może mniej niż dwadzieścia osób na świecie faktycznie umie używać .gc () - Pracowałem wczoraj przez kilka godzin nad centralnym / krytycznym struktura danych z wykorzystaniem danych wygenerowanych przez SecureRandom, gdzieś tuż ponad 40 000 obiektów vm zwolniłoby, jakby zabrakło wskaźników. Najwyraźniej dławił się 16-bitowymi tabelami wskaźników i wykazywał klasyczne zachowanie „niesprawnej maszynerii”.

Próbowałem -Xms i tak dalej, trochę kręciłem się, dopóki nie skończyło się to około 57, xxx czegoś. Następnie uruchomiłoby gc, zaczynając od powiedzmy 57 127 do 57 128 po gc () - w przybliżeniu w tempie rozdętego kodu w obozie Easy Money.

Twój projekt wymaga gruntownej przeróbki, prawdopodobnie podejścia z przesuwanym oknem.

Nicholas Jordan
źródło
1
Mam coś takiego, wiele obiektów w pamięci, których nie mogę cofnąć. Zgłoszono wyjątek OutOfMemory, chcę zmusić GC do przetestowania, czy istnieje proces tworzenia nieskończonego obiektu lub te obiekty są używane przez mój system.
Wygląda na to, że pracujesz nad tym samym problemem, co ja, proszę wyjaśnić: „Tworzenie obiektu Infinite Object” ... dobry projekt badawczy, może możesz tutaj napisać pytanie lub coś w obszarze java (jestem tu trochę nowy i nie znam „Finite Automa”, jak działa strona) Próbowałem wczoraj i skończyłem na tworzeniu pliku.dat, ponieważ kompilator narzekał na „zbyt dużo kodu” na 40 000 podstawowych36 BigIntegers zakodowanych jako statyczny końcowy ciąg [] Będę trzymać się za szyję tutaj i spekuluj, że cała JVM jest ograniczona do wskaźników 16-bitowych, założę się, że musimy agresywnie zerować i czytać z dysku ...
Nicholas Jordan
Naprawdę nie rozumiem cię. Ale żeby być jasnym na temat „Infinite Object Creation”, miałem na myśli, że w moim wielkim systemie jest jakiś fragment kodu do tworzenia obiektów, które obsługują i żyją w pamięci, nie mogłem dostać tego fragmentu kodu, tylko gest !!
5
Nonsens! Jest jeden oczywisty przypadek, w którym należy go użyć: testowanie kodu, który używa słabych referencji, abyśmy mogli upewnić się, że zachowanie jest prawidłowe, gdy słabe referencje zostaną usunięte.
Elias Vasylenko
6

Specyfikacja JVM nie mówi nic konkretnego o odśmiecaniu. Z tego powodu dostawcy mogą swobodnie wdrażać GC na swój sposób.

Tak więc ta niejasność powoduje niepewność w zachowaniu podczas wyrzucania elementów bezużytecznych. Powinieneś sprawdzić swoje dane JVM, aby wiedzieć o podejściach / algorytmach czyszczenia pamięci. Istnieją również opcje dostosowywania zachowania.

rai.skumar
źródło
4

Jeśli chcesz wymusić wyrzucanie elementów bezużytecznych, być może powinieneś rozważyć sposób zarządzania zasobami. Czy tworzysz duże obiekty, które pozostają w pamięci? Czy tworzysz duże obiekty (np. Klasy graficzne), które mają Disposableinterfejs i nie wywołują go dispose()po zakończeniu ? Czy deklarujesz coś na poziomie klasy, czego potrzebujesz tylko w ramach jednej metody?

Bob Kaufman
źródło
2

Byłoby lepiej, gdybyś opisał powód, dla którego potrzebujesz zbierania śmieci. Jeśli używasz SWT, możesz pozbyć się zasobów takich jak Imagei Fontzwolnić pamięć. Na przykład:

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

Istnieją również narzędzia do określania niewykorzystanych zasobów.

Paul Lammertsma
źródło
co jeśli nie ma żadnej metody usuwania?
ArifMustafa,
1
Całkowicie niezwiązany z pytaniem! Nie, nie używam SWT. Nazywam metodę JNI, która otwiera okno .NET przez natywną warstwę Delphi. Mam również rdzeń obliczeniowy FORTRAN, który odbiera dane przez natywną warstwę C ++. Co to ma z tym wspólnego? Czy mogę wymusić GC, czy nie? Nie? :-(
Mostafa Zeinali
0

Jeśli kończy Ci się pamięć i dostajesz OutOfMemoryException, możesz spróbować zwiększyć ilość sterty dostępnej dla java, uruchamiając program java -Xms128m -Xmx512mzamiast zamiast java. To da ci początkową wielkość sterty 128 Mb i maksymalnie 512 Mb, czyli znacznie więcej niż standardowe 32 Mb / 128 Mb.

Viktor Dahl
źródło
Domyślne ustawienia pamięci tojava -Xms512M -Xmx1024M
ThePyroEagle,
0

Inną opcją jest nie tworzenie nowych obiektów.

Buforowanie obiektów jest niedostępne , aby zmniejszyć potrzebę GC w Javie.

Pula obiektów na ogół nie będzie szybsza niż tworzenie obiektów (szczególnie w przypadku lekkich obiektów), ale jest szybsza niż odśmiecanie. Jeśli utworzono 10 000 obiektów, a każdy obiekt miał 16 bajtów. To 160 000 bajtów, które GC musi odzyskać. Z drugiej strony, jeśli nie potrzebujesz wszystkich 10 000 jednocześnie, możesz utworzyć pulę do recyklingu / ponownego wykorzystania obiektów, co eliminuje potrzebę konstruowania nowych obiektów i eliminuje potrzebę GC starych obiektów.

Coś takiego (nieprzetestowane). A jeśli chcesz, aby był wątkowo bezpieczny, możesz zamienić LinkedList na ConcurrentLinkedQueue.

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
źródło
0

Na OracleJDK 10 z G1 GC, pojedyncze wywołanie System.gc()spowoduje, że GC wyczyści Starą Kolekcję. Nie jestem pewien, czy GC działa natychmiast. Jednak GC nie posprząta Young Collection, nawet jeśli System.gc()jest wywoływany wiele razy w pętli. Aby GC wyczyścił Young Collection, musisz przydzielić w pętli (np. new byte[1024]) Bez wywoływania System.gc(). Dzwonienie System.gc()z jakiegoś powodu uniemożliwia GC oczyszczenie kolekcji Young.

Nathan
źródło
0

Naprawdę nie rozumiem cię. Ale żeby być jasnym na temat „Infinite Object Creation”, miałem na myśli, że w moim wielkim systemie jest jakiś fragment kodu do tworzenia obiektów, które obsługują i żyją w pamięci, nie mogłem dostać tego fragmentu kodu, tylko gest !!

To jest poprawne, tylko gest. Masz prawie standardowe odpowiedzi podane już przez kilka plakatów. Weźmy to jeden po drugim:

  1. Nie mogłem dostać tego fragmentu kodu

Zgadza się, nie ma rzeczywistego jvm - taka jest tylko specyfikacja, garść informatyki opisująca pożądane zachowanie ... Niedawno zacząłem inicjować obiekty Java z kodu natywnego. Aby uzyskać to, czego chcesz, jedynym sposobem jest wykonanie agresywnego zerowania. Błędy, jeśli popełnione źle, są tak złe, że musimy ograniczyć się do pierwotnego zakresu pytania:

  1. jakiś fragment kodu w moim dużym systemie tworzy obiekty

Większość plakatów tutaj zakłada, że ​​mówisz, że pracujesz nad interfejsem, jeśli tak, będziemy musieli sprawdzić, czy otrzymujesz cały obiekt czy jeden element na raz.

Jeśli nie potrzebujesz już obiektu, możesz przypisać do niego wartość NULL, ale jeśli się pomylisz, wygenerowany zostanie wyjątek wskaźnika NULL. Założę się, że możesz osiągnąć lepszą pracę, jeśli używasz NIO

Za każdym razem, gdy ty, ja lub ktokolwiek inny dostaje: „ Proszę, potrzebuję tego okropnie. ” Jest to prawie uniwersalny prekursor prawie całkowitego zniszczenia tego, nad czym próbujesz pracować ... napisz do nas mały przykładowy kod, odkażając go użyty kod i pokaż nam swoje pytanie.

Nie denerwuj się. Często rozwiązuje to problem z tym, że dba używa pakietu kupionego gdzieś, a oryginalny projekt nie jest dostosowany do ogromnych struktur danych.

To jest bardzo powszechne.

Nicholas Jordan
źródło
-1

Do Twojej wiadomości

Wywołanie metody System.runFinalizersOnExit (true) gwarantuje, że metody finalizatora zostaną wywołane przed zamknięciem Java. Jednak ta metoda jest z natury niebezpieczna i została uznana za przestarzałą. Alternatywą jest dodanie „haków zamykania” za pomocą metody Runtime.addShutdownHook.

Masarrat Siddiqui

Masarrat Siddiqui
źródło
Wadą haków zamykających jest to, że rzadko faktycznie działają. Wymuszone zakończenie nie działa, niezerowy kod wyjścia nie działa, a czasami (oficjalna) JVM po prostu nie uruchamia ich tak długo, jak potrzebujesz.
ThePyroEagle,
-1

Istnieje jakiś pośredni sposób na wymuszenie śmieciarza. Musisz tylko wypełnić stertę obiektami tymczasowymi, aż do momentu, w którym uruchomi się moduł czyszczenia pamięci. Stworzyłem klasę, która wymusza w ten sposób zbieranie śmieci:

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;
    }

}

Stosowanie:

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

Nie wiem, jak bardzo ta metoda jest przydatna, ponieważ stale wypełnia stertę, ale jeśli masz krytyczną aplikację, która MUSI wymusić GC - kiedy może to być przenośny sposób na wymuszenie GC w Javie.

Agnius Vasiliauskas
źródło
Co to jest „final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;”?
Koray Tugay,
Rozmiar tablicy - ile obiektów tymczasowych (int) zostanie wygenerowanych, aby GC zaczął działać.
Agnius Vasiliauskas,
Czy to jest poprawne: „_” w liczbie całkowitej?
Koray Tugay,
1
Tak, podkreślenia w literałach numerycznych obowiązują od Java SE 7. Jest to przydatne na przykład jako separator tysięcy w liczbach całkowitych, jak w tym przypadku.
Agnius Vasiliauskas,
3
Nigdy nie powinieneś uruchamiać takiego kodu w systemie produkcyjnym. Chociaż ten kod działa w jednym wątku, każdy inny wątek może również otrzymać wyjątek OutOfMemoryException, ale całkowicie odwróć zamiar wywołania go w pierwszej kolejności ...
Steffen Heil
-1

Chciałbym tu coś dodać. Należy pamiętać, że Java nie działa na maszynie wirtualnej, a nie na rzeczywistej maszynie. Maszyna wirtualna ma swój własny sposób komunikacji z maszyną. Może różnić się w zależności od systemu. Teraz, gdy dzwonimy do GC, prosimy Wirtualną Maszynę Javy o wywołanie Garbage Collector.

Ponieważ Garbage Collector jest wyposażony w maszynę wirtualną, nie możemy zmusić go do przeprowadzenia czyszczenia tam i wtedy. Zamiast tego ustawiamy w kolejce nasze żądanie do Garbage Collector. Zależy to od maszyny wirtualnej, po określonym czasie (może się to zmieniać z systemu na system, zwykle gdy pamięć progowa przydzielona do JVM jest pełna), rzeczywista maszyna zwolni miejsce. :RE

Saubhagya Ranjan Das
źródło
Pierwsze zdanie drugiego akapitu jest non sequitur .
Markiz Lorne
-1

Poniższy kod pochodzi z metody assertGC (...). Próbuje zmusić niedeterministyczny kolektor śmieci do zbierania.

   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);

Źródło (dodałem kilka komentarzy dla jasności): Przykład NbTestCase

H. Hess
źródło
-1

Możesz spróbować użyć Runtime.getRuntime().gc()lub użyć metody narzędzia System.gc()Uwaga: Te metody nie zapewniają GC. Ich zakres powinien być ograniczony do JVM, a nie programowo obsługiwać go w aplikacji.

nabster
źródło
2
Jak wyjaśniono w innych odpowiedziach, metody te nie wymuszają (pełnego) uruchomienia odśmiecania.
Flow
-2

Jeśli używasz JUnit i Spring, spróbuj dodać to w każdej klasie testowej:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
Aliuk
źródło