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?
java
garbage-collection
Robert Columbia
źródło
źródło
Odpowiedzi:
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.źródło
non-deterministic == trouble
GC.Collect()
nie zbiera. W Javiegc()
robi.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:
źródło
PhantomReference
z,ReferenceQueue
a 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.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ływanySystem.gc()
. Szansa na osiągnięcie 2 jest dość niewielka.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ź.
źródło
Korzystanie z Java ™ Virtual Machine Interface Tool (JVM Ti) , funkcja
„Zmusi maszynę wirtualną do wyrzucania elementów bezużytecznych”. Interfejs JVM TI jest częścią architektury debugera platformy JavaTM (JPDA) .
źródło
TAK , prawie można zmusić cię do wywoływania metod w tej samej kolejności, a jednocześnie są to:
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 przezfinalize()
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.
źródło
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 ...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?”.
źródło
Aby ręcznie zażądać GC (nie z System.gc ()):
źródło
.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.
źródło
Możesz uruchomić GC z wiersza poleceń. Jest to przydatne dla partii / crontab:
Widzieć :
źródło
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.
źródło
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ą
Disposable
interfejs i nie wywołują godispose()
po zakończeniu ? Czy deklarujesz coś na poziomie klasy, czego potrzebujesz tylko w ramach jednej metody?źródło
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
Image
iFont
zwolnić pamięć. Na przykład:Istnieją również narzędzia do określania niewykorzystanych zasobów.
źródło
Jeśli kończy Ci się pamięć i dostajesz
OutOfMemoryException
, możesz spróbować zwiększyć ilość sterty dostępnej dla java, uruchamiając programjava -Xms128m -Xmx512m
zamiast zamiastjava
. To da ci początkową wielkość sterty 128 Mb i maksymalnie 512 Mb, czyli znacznie więcej niż standardowe 32 Mb / 128 Mb.źródło
java -Xms512M -Xmx1024M
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.
źródło
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śliSystem.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ływaniaSystem.gc()
. DzwonienieSystem.gc()
z jakiegoś powodu uniemożliwia GC oczyszczenie kolekcji Young.źródło
To jest poprawne, tylko gest. Masz prawie standardowe odpowiedzi podane już przez kilka plakatów. Weźmy to jeden po drugim:
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:
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.
źródło
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
źródło
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:
Stosowanie:
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.
źródło
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
źródło
Poniższy kod pochodzi z metody assertGC (...). Próbuje zmusić niedeterministyczny kolektor śmieci do zbierania.
Źródło (dodałem kilka komentarzy dla jasności): Przykład NbTestCase
źródło
Możesz spróbować użyć
Runtime.getRuntime().gc()
lub użyć metody narzędziaSystem.gc()
Uwaga: Te metody nie zapewniają GC. Ich zakres powinien być ograniczony do JVM, a nie programowo obsługiwać go w aplikacji.źródło
Jeśli używasz JUnit i Spring, spróbuj dodać to w każdej klasie testowej:
źródło