2013-03-26 6 views
10

Moja aplikacja ma wiele iteracji. Do tej pory nie napotkałem żadnych problemów z pamięcią. Ale z poziomu kodu mogę podejrzewać, że jest mało miejsc, co powoduje wycieki pamięci i problem z pamięcią. Myślę o ręcznym wywołaniu wywołania śmieciarki. Czy dobrą praktyką jest ręczne wywoływanie Garbage Collectora?Czy możemy nazwać Garbage Collectora jawnie?

+0

Wydaje mi się, że to pytanie zostało już omówione: http://stackoverflow.com/questions/2414105/why-is-it-a-bad-practice-to-call-system-gc –

Odpowiedz

26

można wywołać za pomocą śmieciarza:

System.gc(); 

Ale to nie znaczy, że to będzie realizowane natychmiast. JVM decyduje, kiedy ją wykonać. Ogólnie, jeśli JVM ma zamiar rzucić OutOfMemoryError, wywołanie System.gc() nie uniemożliwi tego. Lepiej zbadaj, dlaczego tracisz tak dużo pamięci i oczyść ją po drodze.

JavaDoc:

Wywołanie metody GC sugeruje, że wirtualna maszyna Java wydać wysiłek ku recykling nieużywanych obiektów w celu uczynienia pamięć one zajmują obecnie dostępna dla szybkiego ponownego użycia. Kiedy kontrola powraca od wywołania metody, Java Virtual Machine dokonał wszelkich starań, aby odzyskać przestrzeń ze wszystkich wyrzuconych przedmiotów

+9

+1 I ' d również dodać, że wywołanie System.gc może faktycznie obniżyć wydajność aplikacji – MadProgrammer

+3

Myślę, że byłoby miło mieć listę przypadków, w których wywoływanie 'System.gc()' * jest * użyteczne. Jednym z przypadków jest próba oszacowania wykorzystania pamięci podczas debugowania/programowania (nie produkcji). Innym przypadkiem jest niewiarygodna próba wywoływania finalizatorów, analizowania wycieków pamięci, ponownie podczas programowania. –

+1

@Thomas, finalizery/klasy śmieci są podstawowymi powodami, finalizatory zasobów systemowych, takich jak DirectBuffers/Deskryptory plików są ważne. Więcej opcji jmap w/live wywołuje kolekcję śmieci. Istnieje kilka opcji -XX, które wpływają na to, co dzieje się podczas połączenia jawnego (w tym zupełnie nic). Istnieje kilka innych przypadków, które mogą mieć pozytywny wpływ na to, że skompaktowaliśmy kupioną stertę (jeśli zagęszczanie i magazynowanie są w rzeczywistości opcjami w/wybranym kolektorze). – bestsss

8

Czy to dobra praktyka, aby ręcznie wywołać Garbage Collector?

Nie, zdecydowanie nie jest to dobra praktyka.

Można użyć System.gc(). Zauważ, że nie można zagwarantować, że wywołasz to odśmiecenie - daje to tylko wskazówkę dla systemu, że dobrze jest zrobić zbieranie śmieci.

Śmieciarka w wirtualnej maszynie JVM firmy Oracle zawiera dużo wyrafinowanej logiki, aby określić, kiedy i co należy czyścić. Dostrajanie wymaga znajomości szczegółów dotyczących działania. Samo umieszczenie System.gc() gdzieś w twoim programie prawdopodobnie nie pomoże dużo, a nawet może nawet pogorszyć sytuację.

Zobacz Java SE 6 HotSpot Virtual Machine Garbage Collection Tuning szczegółowe informacje o tym, jak dostroić zbieranie śmieci z Java SE 6.

+3

* Nie, zdecydowanie nie jest to dobra praktyka. * Nie zgadzam się, jeśli wiesz, dlaczego to nazywasz, jest to dobra okazja. Miało to jednak zastosowanie do niektórych kodów monitorowania. Podam przykład wywołania MappedByteBuffer.map, musisz go sfinalizować, a jedyna opcja nie-hackowa obejmuje GC. – bestsss

+0

@bestsss - Zinterpretowałem "dobrą praktykę" jako "coś, co jest zwykle dobrą rzeczą do zrobienia", a wywołanie GC ręcznie zdecydowanie nie jest czymś, co normalnie powinieneś zrobić - tylko zrób to, jeśli naprawdę wiesz, co robisz kiedy możesz udowodnić sobie, że jest to korzystne. – Jesper

+0

Oczywiście zawołanie bez powodu, to zły pomysł. btw, literówka w poprzednim komentarzu: MappedByteBuffer. * Odmów * – bestsss

3

niezależnie od tego czy może lub nie może ręcznie wywołać śmieciarza (i różne poziomy zbiórki), i jaki wpływ ma to na wydajność (która w istocie jest a topic worth discussion), nie zapobiegnie OutOfMemoryErrors, ponieważ gdy JVM wkrótce zabraknie pamięci, robi to najbardziej dokładną kolekcję, którą i tak może. Tylko wtedy, gdy po tej kolekcji nie ma wystarczającej ilości pamięci, wystąpi błąd. Nawet jeśli sam uruchomisz kolekcję wcześniej, wynik (ilość odzyskanej pamięci) jest taki sam.

Nie można usunąć przecieków pamięci przez częstsze uruchamianie czyszczenia pamięci.

Muszą zostać naprawione w twoim programie (przestań wskazywać rzeczy, których już wcześniej nie potrzebujesz) lub (najgorszy przypadek, jeśli jest to "prawdziwy" przeciek) w samej JVM lub bibliotece uruchomieniowej (ale w prawdziwej pamięci) błędy zarządzania nie powinny już istnieć po tylu latach pracy).

6

Możesz wywołać Garbage Collector jawnie, ale JVM decyduje, czy przetworzyć połączenie, czy nie. Idealnie, nie powinieneś nigdy pisać kodu zależnego od wywołania do garbage collectora.

JVM wewnętrznie używa jakiegoś algorytmu, aby zdecydować, kiedy wykonać to połączenie. Kiedy nawiązujesz połączenie, używając System.gc(), jest to tylko żądanie do JVM, a JVM może w każdej chwili zdecydować, aby je zignorować.

5

Tak można jawnie wywołać śmieciarza korzystając

System.gc(); 

ale to, co się dzieje, że nie można zamówić JVM natychmiast zrobić zbierania śmieci. JVM sam decyduje, kiedy je zbierać. Nie jest to dobry pomysł na wywoływanie go ręcznie.

Ponadto w odniesieniu do OutOfMemoryException ręczne usuwanie pamięci nie pomoże zapobiec wyjątkowi, ponieważ JVM zgłasza ten wyjątek po odzyskaniu całej dostępnej pamięci. Posiada kilka bardzo wyrafinowanych algorytmów, które określają, kiedy i jak wykonać usuwanie śmieci. Proponuję więc, aby po uzyskaniu OutOfMemoryException ponownie sprawdzić program, aby był bardziej wydajny lub zwiększyć przestrzeń sterty.