Menu Zamknij

Jak szybko i skutecznie znaleźć wycieki pamięci w Javie.

Wycieki pamięci nie muszą być trudną zagadką. Gdy pamięć ucieka i nie wiadomo tak naprawdę czym zawiniliśmy warto użyć, chociażby takiego narzędzia, jak Java VisualVM.

Wycieki pamięci

Aby odnaleźć wycieki pamięci w naszych programach, należy zaopatrzyć się w pewne proste narzędzie Java VisualVM  do pobrania z tej strony https://visualvm.github.io/.

Dodatkowo można pobrać gotowy już program wywołujący wycieki pamięci oraz jego kod źródłowy.

MeomoryLeakDesktopTester-app

MemoryLeakDektopTester-src

Uruchamiamy najpierw  program Java VisualVM

Uruchomienie VisualVM

Teraz możemy uruchomić program wywołujący wyciek pamięci. Można pobrać i uruchomić Memory Leak Desktop Tester lub jakąś własną z tego typu problemem aplikację. Ja posłużę się wyżej wymienioną.

Testowanie wycieku

Teraz możemy zauważyć, że nasz program jest widoczny w programie Java VisualVM. Należy go wybrać z listy i kliknąć dwukrotnie. W pierwszej zakładce znajdziemy kilka ogólnych informacji o monitorowanej aplikacji.

Uruchomienie VisualVM

W kolejnej zakładce Monitor można oglądać bieżący wpływ aplikacji na środowisko wirtualnej maszyny Javy (JVM), wykorzystanie procesora, pamięci, liczbę używanych klas, oraz liczbę wątków. Z tego miejsca może również wywołać Garbage Collector klikając Perform GC, jak i zrobić zrzut pamięci klikając Heap Dump.

Monitorowanie JVM

Następna zakładka pozwala na dokładniejsze monitorowanie działania wątków w aplikacji. Oprócz podstawowych informacji o ilości wątków widziana jest bieżąca lista poszczególnych wątków działających w naszej aplikacji oraz ich stan w skali czasu jak ich  czas działania. W tym miejscu możemy również zrobić zrzut tych danych klikając Thrad Damp. Monitorowanie przebiegu wykonania wątków daje nam możliwość również wykrycie zakleszczeń.

Monitorowanie wyjątków

Kolejną zakładka Sampler pozwala na testowanie działania aplikacji pod względem czasu wykonywania metod, ilości wykonanych metod, pozwala sprawdzić, w jakim stopniu korzystają one z czasu procesora.

Sampler

Oprócz tego możliwe jest również monitorowanie wątków pod względem wykorzystania czasu procesora.

Sampler

Sampler pozwala również na proste badanie pamięci pod względem liczby instancji oraz ogólnym rozmiarze wszystkich obiektów z danego typu. Dodatkowo umożliwia również monitorowanie pamięć pod względem wykorzystywania jej przez działające wątki.

Badanie zużycia pamięci dla typów
Badanie zużycia pamięci dla wątków

Najbardziej interesująca nas zakładką jest Profiler. To tu odpowiednio konfigurując narzędzie, jesteśmy w stanie dokładnie wyśledzić metodę, która jest powodem wycieku pamięci. Zaznaczamy Settings wybieramy na dole ekranu zakładkę Memory Settings. Następnie zaznaczamy Record allocations stack traces.

Śledzenie wycieków

Teraz klikamy Memory, a następnie wywołujemy funkcjonalność powodującą wyciek pamięci w naszym programie. W moim przypadku będzie to kliknięcie Start w programie  Memory Leak Tester.

Wycieki pamięci JAVA

Czkamy aż profiler zbierze odpowiednią ilość danych do sprawdzania naszego wycieku. W przypadku mojego programu jest to czas około minuty. Następnie klikamy na Snapshot aby zapisać zebrane podczas analizy informacje o działaniu programu.

Snapshot pamięci

Gdy wykonamy już Snapshot możemy przejść  do niego i sprawdzić zarwate w nim informacje. Segregujemy po kolumnie Live Bytes, czyli obiektach, które zajęły najwięcej pamięci w  trakcie działania programu. W moim przypadku są to obiekty typu  byte[] i ConcurentLinkedQueue$Node. Zaznaczam więc na początek byte[] i klikam prawym Show Allocation Stack Traces. Następnie ukazuje mi się poniższy ekran.

Wycieki pamięci JAVA

Tutaj znów sortujemy  dane po kolumnie Live Bytes i od razu można zauważyć, że w drugim wierszu jest wyświetlony pakiet oraz klasa w nim zawarta wraz ze szkodliwą metoda wytwarzającą nadmierną ilość obiektów typy byte[], która powoduje wycieki pamięci. Dzięki temu będziemy mogli łatwo odnaleźć odpowiedzialny za to kod w naszym programie.

Wycieki pamięci JAVA

Sprawdźmy jeszcze, skąd się biorą obiekty drugiej wspomnianej klasy, czyli ConcurentLinkedQueue$Node. Klikamy na poniższej zakładce Memory Results i sprawdzamy w ten sam sposób skąd nagromadzenie tych drugich obiektów. Jak widać na poniższym obrazku, winna jest ta sama metoda.

Wycieki pamięci JAVA

No i się znalazła się nasza winowajczyni. Teraz już wiemy w jakim pakiecie, klasie i jakiej metodzie tkwi problem z naszym wyciekiem pamięci.

Please follow and like us:
Skuteczna refaktoryzacja w 10 krokach!

Odbierz Darmowy Poradnik o Refaktoryzacji!

Poznaj kilka prostych technik i wprowadź nową jakość w swoim projekcie.

Dzięki za dołączenie do mojej listy.

Coś poszło nie tak :( Spróbuj jeszcze raz.