Jak znaleźć wyciek pamięci Java

Jak znaleźć wyciek pamięci w Javie (używając np. JHat)? Próbowałem załadować zrzut sterty w JHat, aby spojrzeć na podstawowe. Jednak nie rozumiem, jak mam być w stanie znaleźć referencję root (ref) czy jak to się nazywa. Zasadniczo mogę powiedzieć, że jest kilkaset megabajtów wpisów w tabeli hash ([java.util.HashMap$Entry lub coś w tym stylu), ale mapy są używane wszędzie... Czy jest jakiś sposób na wyszukiwanie dużych map, czy być może znaleźć ogólne korzenie drzew dużych obiektów?

[Edytuj] Ok, do tej pory przeczytałem odpowiedzi, ale powiedzmy, że jestem tanim draniem (czyli bardziej interesuje mnie nauka korzystania z JHat niż płacenie za JProfiler). Ponadto JHat jest zawsze dostępny, ponieważ jest częścią JDK. Chyba, że z Jhatem nie ma mowy, ale brutalna siła, ale nie mogę uwierzyć, że tak może być.

Również, nie sądzę, że będę w stanie faktycznie modyfikować (dodanie logowania wszystkich rozmiarów map) i uruchom go na tyle długo, żebym zauważył przeciek.

Author: Community, 2008-09-02

9 answers

Stosuję następujące podejście do znajdowania wycieków pamięci w Javie. Korzystałem z jprofilera z wielkim sukcesem, ale wierzę, że każde specjalistyczne narzędzie z możliwościami graficznymi (diffy są łatwiejsze do analizy w formie graficznej) zadziała.

  1. Uruchom aplikację i poczekaj, aż osiągnie stan "stabilny", po zakończeniu inicjalizacji i bezczynności aplikacji.
  2. Uruchom operację podejrzewaną o spowodowanie wycieku pamięci kilka razy, aby umożliwić dowolną pamięć podręczną, związaną z DB inicjalizacja ma się odbyć.
  3. Uruchom GC i Zrób migawkę pamięci.
  4. Uruchom operację jeszcze raz. W zależności od złożoności operacji i rozmiarów przetwarzanych danych operacja może wymagać wykonania od kilku do wielu razy.
  5. Uruchom GC i Zrób migawkę pamięci.
  6. Uruchom diff dla 2 migawek i przeanalizuj go.

Zasadniczo analiza powinna zaczynać się od największego pozytywnego rozróżnienia przez, powiedzmy, typy obiektów i znaleźć to, co powoduje, że te dodatkowe obiekty przyklejają się do pamięć.

Dla aplikacji internetowych, które przetwarzają żądania w kilku wątkach, analiza staje się bardziej skomplikowana, ale mimo to nadal obowiązuje ogólne podejście.

Wykonałem sporo projektów mających na celu zmniejszenie pamięci aplikacji i to ogólne podejście z pewnymi poprawkami i sztuczkami dotyczącymi konkretnych aplikacji zawsze działało dobrze.

 118
Author: Dima Malenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 18:49:35

Pytający tutaj muszę powiedzieć, że uzyskanie narzędzia, które nie zajmuje 5 minut, aby odpowiedzieć na każde kliknięcie, znacznie ułatwia znalezienie potencjalnych wycieków pamięci.

Ponieważ ludzie sugerują kilka narzędzi (próbowałem tylko visual WM, ponieważ dostałem to w JDK i JProbe trial ) pomyślałem, że powinienem zaproponować darmowe / open source narzędzie zbudowane na platformie Eclipse, analizator pamięci (czasami określany jako analizator pamięci SAP) dostępny na http://www.eclipse.org/mat /.

Co jest naprawdę fajne w tym narzędziu jest to, że indeksowane zrzut sterty, kiedy po raz pierwszy otworzył go, co pozwoliło mu pokazać dane jak zachowana sterta bez czekania 5 minut dla każdego obiektu (prawie wszystkie operacje były ton szybciej niż inne narzędzia próbowałem).

Po otwarciu zrzutu, pierwszy ekran pokazuje wykres kołowy z największymi obiektami (licząc zachowaną stertę) i można szybko przejść w dół do obiektów, które są duże dla wygody. Ma również znaleźć prawdopodobnie przeciek podejrzanych, które reccon może się przydać, ale ponieważ nawigacja była dla mnie wystarczająca, tak naprawdę nie dostałem się do niego.

 47
Author: jwiklund,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-11 17:17:07

Narzędzie jest bardzo pomocne.

Są jednak chwile, kiedy nie można użyć narzędzia: zrzut sterty jest tak ogromny, że powoduje awarię narzędzia, próbujesz rozwiązać problem z maszyną w środowisku produkcyjnym, do której masz tylko dostęp do powłoki itp.

W takim przypadku, pomaga znać drogę wokół pliku zrzutu hprof.

Szukaj stron. To pokazuje, jakie obiekty zużywają najwięcej pamięci. Ale obiekty nie są sumowane ze sobą wyłącznie według typu: każdy wpis zawiera również "trace" ID. Następnie można wyszukać "TRACE nnnn" , aby zobaczyć kilka pierwszych klatek stosu, w którym obiekt został przydzielony. Często, gdy widzę, gdzie obiekt jest przydzielony, znajduję błąd i kończę. Zauważ również, że możesz kontrolować liczbę klatek zapisanych w stosie za pomocą opcji-Xrunhprof.

Jeśli sprawdzasz witrynę alokacji i nie widzisz nic złego, musisz rozpocząć łączenie wstecz z niektórych żywych obiektów do obiektów root, aby znaleźć nieoczekiwane łańcuch odniesienia. To tutaj narzędzie naprawdę pomaga, ale możesz zrobić to samo ręcznie(dobrze, z grep). Nie ma tylko jednego głównego obiektu (tzn. obiektu nie podlegającego garbage collection). Wątki, klasy i ramki stosu działają jak obiekty główne, a wszystko, do czego się odwołują, nie podlega kolekcjonowaniu.

Aby wykonać łańcuchowanie, poszukaj w sekcji zrzutu sterty wpisów z identyfikatorem bad trace. Spowoduje to przejście do wpisu OBJ lub ARR, który pokazuje unikalny identyfikator obiektu w szesnastkowo. Szukaj wszystkich wystąpień tego identyfikatora, aby znaleźć, kto ma silne odniesienie do obiektu. Podążaj każdą z tych ścieżek do tyłu, aż dowiesz się, gdzie jest wyciek. Widzisz, dlaczego narzędzie jest tak poręczne?

Statyczne elementy są recydywistą za wycieki pamięci. W rzeczywistości, nawet bez narzędzia, warto poświęcić kilka minut na przeglądanie kodu statycznych członków Mapy. Czy mapa może urosnąć? Czy coś czyści jego wpisy?

 12
Author: erickson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 18:30:42

W większości przypadków w aplikacjach korporacyjnych podana sterta Java jest większa niż idealny rozmiar max 12 do 16 GB. Trudno mi było sprawić, by NetBeans profiler działał bezpośrednio na tych dużych aplikacjach java.

Ale zazwyczaj nie jest to potrzebne. Możesz użyć narzędzia jmap dołączonego do jdk, aby zrobić zrzut sterty" na żywo", czyli jmap zrzuci stertę po uruchomieniu GC. Wykonaj jakąś operację na aplikacji, poczekaj aż operacja zostanie zakończona, a następnie wykonaj kolejny "live" zrzut sterty. Użyj narzędzi takich jak Eclipse MAT, aby załadować hałdy, posortować na histogramie, zobaczyć, które obiekty wzrosły, lub które są najwyższe, to daje wskazówkę.

su  proceeuser
/bin/jmap -dump:live,format=b,file=/tmp/2930javaheap.hrpof 2930(pid of process)

Jest tylko jeden problem z tym podejściem; Ogromne wysypiska, nawet z opcją live, mogą być zbyt duże, aby przenieść je do fazy rozwojowej i mogą potrzebować maszyny z wystarczającą ilością pamięci / PAMIĘCI RAM, aby je otworzyć.

Tutaj pojawia się histogram klasy. Za pomocą narzędzia jmap można zrzucać histogram klasy NA ŻYWO. To poda tylko klasę histogram użycia pamięci.Zasadniczo nie będzie miał informacji, aby połączyć odniesienie. Na przykład może umieścić tablicę znaków na górze. I klasa strun gdzieś poniżej. Sam musisz to połączyć.

jdk/jdk1.6.0_38/bin/jmap -histo:live 60030 > /tmp/60030istolive1330.txt

Zamiast robić dwa zrzuty, weź dwa histogramy klasy, jak opisano powyżej; następnie porównaj histogramy klasy i zobacz klasy, które się zwiększają. Sprawdź, czy możesz powiązać klasy Java z klasami aplikacji. To będzie daj mi dobrą wskazówkę. Oto skrypt pythons, który może pomóc Ci porównać dwa zrzuty histogramu JMAP. histogramparser.py

Wreszcie narzędzia takie jak JConolse i VisualVm są niezbędne, aby zobaczyć wzrost pamięci w czasie i sprawdzić, czy nie ma wycieku pamięci. Wreszcie czasami Twoim problemem może nie być wyciek pamięci, ale wysokie zużycie pamięci.W tym celu Włącz rejestrowanie GC; użyj bardziej zaawansowanego i nowego kompaktowania GC, takiego jak G1GC; i możesz użyć narzędzi jdk, takich jak jstat, aby zobaczyć zachowanie GC live

jstat -gccause pid <optional time interval>

Inne odwołania do google for-jhat, jmap, Full GC, Humongous allocation, G1GC

 7
Author: Alex Punnen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-02 08:47:59

Istnieją narzędzia, które powinny pomóc Ci znaleźć wyciek, takie jak JProbe, YourKit, AD4J lub JRockit Mission Control. Ostatni to ten, który osobiście znam najlepiej. Każde dobre narzędzie powinno pozwolić ci zejść do poziomu, na którym możesz łatwo zidentyfikować, jakie wycieki i gdzie są przydzielane nieszczelne obiekty.

Używanie Hashtabli, Hashmaps lub podobnych jest jednym z niewielu sposobów, w jaki można w ogóle wyciekać pamięć w Javie. Gdybym miał znaleźć przeciek ręcznie, drukowałbym periodycznie rozmiar mojego HashMaps, a stamtąd znaleźć ten, w którym dodaję elementy i zapomnieć je usunąć.

 5
Author: Tnilsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 17:48:30

Cóż, zawsze jest małe rozwiązanie techniczne dodawania logowania rozmiaru map po ich modyfikacji, a następnie wyszukiwania dzienników, dla których mapy rosną ponad rozsądny rozmiar.

 4
Author: Mike Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 17:39:50

Naprawdę musisz użyć profilera pamięci, który śledzi alokacje. Spójrz na JProfiler - ich funkcja "heap walker" jest świetna i mają integrację ze wszystkimi głównymi Idami Javy. Nie jest darmowy, ale nie jest też tak drogi (499 USD za jedną licencję) - dość szybko spalisz czas wart 500 USD, próbując znaleźć wyciek za pomocą mniej wyrafinowanych narzędzi.

 0
Author: McKenzieG1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 17:46:46

NetBeans ma wbudowany profiler.

 0
Author: wbkang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 18:30:34

Możesz sprawdzić jconsole . Jest to również część JDK i uważam, że pomocne jest znalezienie wycieków pamięci / referencji w połączeniu z jhat. Zajrzyj również do tego wpisu na blogu.

 -1
Author: JMM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 18:39:08