Pytanie Wielkość sterty Java nie została całkowicie wykorzystana


Obecnie monitoruję moją uruchomioną aplikację java za pomocą Visual VM: http://visualvm.java.net/

Podkreślam użycie pamięci przy pomocy -Xmx128m.

Po uruchomieniu widzę, że rozmiar sterty wzrasta do 128 m (zgodnie z oczekiwaniami), ale używana stuła zbiega się w przybliżeniu na 105 m, zanim napotkam błąd przestrzeni sterty Java.

enter image description here

Dlaczego te pozostałe 20m nie są używane?


16
2018-05-04 10:47


pochodzenie


Czy możesz dołączyć błąd miejsca sterty, który otrzymujesz? Być może jest to problem w permgen? - Paul Whelan
Masz wiele stert, jest "Eden Space", "Przestrzeń Survivor" i "Tenured Gen". I masz pamięć bez sterty. Może w VisualVM jest filtr. A czy twoja aplikacja wymaga 20m? - Thomas Jungblut
Otrzymuję błąd "java.lang.OutOfMemoryError: Java heap space". co masz na myśli przez ".. filtrowanie w VisualWM .."? Obecnie czytam duże pliki (łącznie około 100 MB) i buduję mapę, aby przechowywać określone informacje, więc myślę, że potrzebuję trochę pamięci. - Will
Nie jestem pewien, co się tutaj dzieje. Normalnie powinieneś otrzymać OutOfMemoryError, gdy stertą jest 120MB. Czy możesz utworzyć migawkę aplikacji i wysłać ją do mnie? Czy masz powtarzalne przypadki testowe, które możesz udostępniać? Chciałbym rzucić okiem. - Tomas Hurka


Odpowiedzi:


Stertę dzieli się na Young-Generation (Eden-Space) i dwa Survivor-Spaces o identycznych rozmiarach, zwykle nazywane From i To), Old Generation (Tenured) i Permanent Space.

The Xmx/Xms opcja ustawia ogólnie rozmiar w biodrach. Zatem region (z domyślnym rozmiarem) jest w rzeczywistości Stałą Przestrzenią - i być może, nie znamy szczegółów na temat twojego testu warunków skrajnych, żadne obiekty nie są faktycznie przenoszone z Eden na stałe lub na stałe, więc te regiony pozostają puste, podczas gdy Eden kończy się przestrzeni.


4
2018-05-04 11:28



Myślałem, że perm gen jest przechowywany osobno? - Will
@Will - ja też, ale potem przeczytałem kilka artykułów wyjaśniających, że -Xmx parametr tunes the kompletny sterty (w tym PermGen) i inne flagi, takie jak XX:MaxPermSize dostroić wewnętrzną strukturę sterty - Andreas_D
Thx, czy mógłbyś podać mi link do tego artykułu? - Will
@Will - to ten, który czytam: testing-software.org/Tools/gcview - Andreas_D
Dzięki. Zgodnie z artykułem sterty zawiera PermGen. Jeśli więc VisualVm uznałby, że PermGen nie jest przestrzenią używaną (co nie jest intuicyjne), moje pytanie zostanie rozwiązane. - Will


Musisz zrozumieć centralny fakt dotyczący ergonomii śmieciarki:

Kosztowną częścią zbierania śmieci jest znajdowanie i postępowanie z przedmiotami, które NIE są śmieciami.

Oznacza to, że gdy hałda zbliża się do maksymalnej pojemności, GC będzie wydawać coraz więcej czasu na coraz mniejszy zwrot w odzyskanej przestrzeni. Jeśli GC miałby spróbować wykorzystać każdy ostatni bajt pamięci, wynik netto byłby taki, że twoja JVM spędzałaby coraz więcej czasu na zbieraniu śmieci, aż ... w końcu ... prawie żadna pożyteczna praca nie była wykonywana.

Aby uniknąć tej patologicznej sytuacji, JVM monitoruje stosunek czasu spędzony na GC'ing i wykonując użyteczną pracę. Kiedy stosunek przekracza konfigurowalną wartość progową, GC podnosi OutOfMemoryError ... nawet jeśli (technicznie) dostępna jest wolna pamięć. Prawdopodobnie to widzisz, chociaż inne wyjaśnienia są równie wiarygodne.

Możesz zmieniać progi GC, wielkości generacji, itp. Za pomocą opcji JVM, ale prawdopodobnie lepiej jest tego nie robić. Lepszym pomysłem jest ustalenie, dlaczego wykorzystanie pamięci w aplikacji stale rośnie. Najprawdopodobniej występują wycieki pamięci ... to jest błędy ... w kodzie, które to powodują. Poświęć swój wysiłek na znajdowanie i naprawianie tych błędów, zamiast martwić się, dlaczego nie używasz całej pamięci.

(W rzeczywistości używasz go ... ale nie cały czas).


5
2018-05-04 11:53



Nie otrzymuję przekroczenia limitu limitu GC, ale błąd przestrzeni sterty Java. - Will
@Will - proszę ponownie przeczytać ostatnie 2 akapity ... - Stephen C
Dziękuję za pomoc, ale o ile wiem, opisywany przez ciebie scenariusz dotyczący progu GC spowoduje odrzucenie OutOfMemoryError: przekroczony został górny limit GC. Jednak otrzymany błąd to OutOfMemoryError: java heap space. Więc nie sądzę, że porblem leży w GC, który działa zbyt długo i nie odzyskuje wystarczającej ilości pamięci, ale zamiast wyczerpywania się przestrzeni sterty, z jakiegokolwiek powodu. - Will
"Jakikolwiek powód" najprawdopodobniej jest przeciekiem pamięci i właśnie na tym należy skupić się na wyszukiwaniu i naprawianiu. Fakt, że aplikacja tego nie robi wydaje się być używanie wszystkich tych 128 MB pamięci jest poza tym punktem. Nawet gdyby tak było, nadal byś umarł z powodu wycieku pamięci ... trochę później. - Stephen C
A jeśli masz powody, by martwić się "marnowaniem" 23Mb pamięci ze względu na koszty ogólne GC, prawdopodobnie wybrałeś niewłaściwy język implementacji! - Stephen C


Java dzieli swoją pamięć na generacje. Możesz otrzymać błąd miejsca sterty, jeśli napiszone pokolenie zostanie wypełnione. Zwykle zmieniają rozmiar dynamicznie, ale jeśli ustawisz stały rozmiar, nie będą.


4
2018-05-04 11:14



Nie ustawiłem żadnej innej opcji niż -Xmx128m. - Will
Musisz monitorować podział, który regiony się zapełniają. - Peter Lawrey