Przekroczono limit narzutów GC

93

Jaki jest czas próbkowania używany przez maszynę JVM do zgłaszania „java.lang.OutOfMemoryError: przekroczono limit narzutu GC”? Wiem, że możesz kontrolować 98% i 2% za pomocą parametrów GCTimeLimit i GCHeapFreeLimit, ale jaki jest czas próbkowania?

PRK
źródło

Odpowiedzi:

82

Z Java SE 6 HotSpot [tm] Virtual Machine Garbage Collection Tuning

następujące

Nadmierny czas GC i OutOfMemoryError

Współbieżny moduł zbierający wyrzuci błąd OutOfMemoryError, jeśli zbyt dużo czasu spędza się na usuwaniu elementów bezużytecznych: jeśli ponad 98% całkowitego czasu jest spędzane na usuwaniu elementów bezużytecznych, a mniej niż 2% sterty jest odzyskiwane, zostanie wyrzucony błąd OutOfMemoryError. Ta funkcja została zaprojektowana, aby uniemożliwić uruchamianie aplikacji przez dłuższy czas przy niewielkim lub żadnym postępie, ponieważ sterta jest zbyt mała. W razie potrzeby tę funkcję można wyłączyć, dodając opcję -XX: -UseGCOverheadLimit do wiersza poleceń.

Zasada jest taka sama, jak w przypadku modułu zbierającego równoległego, z tą różnicą, że czas spędzony na wykonywaniu współbieżnych kolekcji nie jest wliczany do 98% limitu czasu. Innymi słowy, tylko kolekcje wykonane, gdy aplikacja jest zatrzymana, wliczają się do nadmiernego czasu GC. Takie kolekcje są zwykle spowodowane awarią trybu współbieżnego lub jawnym żądaniem kolekcji (np. Wywołaniem System.gc ()).

w połączeniu z przejściem dalej na dole

Jedno z najczęściej spotykanych zastosowań jawnego wyrzucania elementów bezużytecznych występuje w przypadku rozproszonego wyrzucania elementów bezużytecznych RMI (DGC). Aplikacje używające RMI odwołują się do obiektów w innych maszynach wirtualnych. Nie można zbierać elementów bezużytecznych w tych aplikacjach rozproszonych bez sporadycznego zbierania lokalnej sterty, więc RMI wymusza okresowo pełne kolekcje. Częstotliwość tych kolekcji można kontrolować za pomocą właściwości. Na przykład,

java -Dsun.rmi.dgc.client.gcInterval=3600000

-Dsun.rmi.dgc.server.gcInterval=3600000 określa jawne zbieranie danych raz na godzinę zamiast domyślnej stawki raz na minutę. Jednak może to również spowodować, że odzyskanie niektórych obiektów zajmie znacznie więcej czasu. Te właściwości mogą być ustawione tak wysoko, jak Long.MAX_VALUE, aby czas między jawnymi kolekcjami był praktycznie nieskończony, jeśli nie ma potrzeby określania górnej granicy terminowości działania DGC.

Wydaje się, że okres oceny w celu określenia 98% wynosi jedną minutę, ale można go skonfigurować w JVM firmy Sun z poprawną definicją.

Oczywiście możliwe są inne interpretacje.

Edwin Buck
źródło
5
Rozproszone wyrzucanie elementów bezużytecznych RMI jest działaniem niezwiązanym z regularnym czyszczeniem pamięci. Więc nie rozumiem, jak możesz wywnioskować, co właśnie zrobiłeś.
Stephen C
2
Wniosek nie jest doskonały ani nawet poprawny, dlatego „wydaje się sugerować” zamiast „implikacji”. Jeśli zgodzisz się z obserwacją, że jeśli ludzie w Sun wykorzystali jedną minutę na określenie interwału zbierania śmieci dla RMI, ten czas zbierania pamięci w zbieraniu równoległym jest kumulowany tylko wtedy, gdy główny program się zatrzymuje, i zrób mały skok wiary , to szanse są dobre, 98% jest zbierane w ciągu jednej minuty. To magiczna liczba, ale jedna minuta to magiczna liczba często używana w porównaniu do powiedzmy 3,5 minuty.
Edwin Buck
@StephenC czy masz na myśli, że nawet jeśli ustawimy -XX:+DisableExplicitGC , nie wpłynie to na konfigurację związaną z RMI, a system będzie wywoływał gc z częstotliwością ustawioną parametrem-Dsun.rmi.dgc.server.gcInterval
Steephen
1
@Steephen - Nie. Nie to mówię. Mówię o tym stwierdzeniu: „Wydaje się sugerować, że okres oceny dla określenia 98% trwa jedną minutę…” . I zauważ, że Edwin zgadza się, że wnioskowanie jest „niedoskonałe”. Wniosek jest oparty na założeniu, że osoby z Sun, które wdrożyły RMI (i DGC), pozostawały w bliskiej komunikacji z osobami, które wdrożyły mechanizm ograniczenia narzutów GC. Podejrzewam, że te dwa wydarzenia faktycznie miały miejsce w różnym czasie. Zauważ, że ta -Dsun.rmi.dgc.server.gcIntervalwłaściwość istnieje od wersji Java 1.2.
Stephen C
1
W każdym razie lepszym podejściem do znalezienia prawdziwej odpowiedzi na to pytanie byłoby przyjrzenie się kodowi źródłowemu OpenJDK.
Stephen C