JAVA exPress logo Published on JAVA exPress (http://www.javaexpress.pl)

W walce o lepszą jakość - odpluskwianie

Jakub Jurkiewicz

Issue 1 (2008-08-18)

W pracy każdego programisty przychodzi taki moment, gdy okazuje się, że nie wszystko działa tak jak przewidział – testy nie przechodzą, produkt nie chce się zbudować, a menedżer projektu pisze maile, że będzie trzeba zostać po godzinach. Na szczęście programista nie pozostaje w takiej sytuacji bezbronny, może wykorzystać sprawdzony od lat mechanizm odpluskiwania (ang. debugging) kodu w celu znalezienia błędów. Eclipse IDE oferuje, niezastąpiony w pracy developera, zestaw narzędzi do analizy kodu podczas jego wykonywania. W artykule tym zostaną przedstawione zarówno podstawowe, jak i bardziej zaawansowane rozwiązania dla odpluskwiania kodu napisanego w języku Java oferowane przez Eclipse IDE w wersji 3.3.

Jak zacząć?

Uruchomienie programu w trybie umożliwiającym odpluskwiania różni się niewiele od uruchomienia aplikacji w trybie standardowym. Z menu głównego wybieramy Run->Open Debug Dialog. Otworzy się nowe okno (Rysunek 1.)

Okno z nową
konfiguracją uruchomienia dla odpluskwiania

Rysunek 1. Okno z nową konfiguracją uruchomienia dla odpluskwiania

Następnie z drzewa po lewej stronie wybieramy istniejącą już konfigurację uruchomienia (ang. launch configuration) dla aplikacji Java (ang. Java Application) lub też tworzymy nową (przycisk New launch configuration). Ustawiamy wszystkie interesujące nas opcje i klikamy przycisk Debug znajdujący się w prawym dolnym rogu okna.

Co istotne Eclipse IDE potrafi uruchomić w tym trybie kod, który zawiera błędy kompilacji (Eclipse IDE do kompilacji wykorzystuje własny kompilator). Jeśli ścieżka wykonywania się kodu osiągnie punkt, w którym istnieje błąd, to wykonywanie się zatrzyma i Eclipse IDE pozwoli poprawić błąd, aby móc kontynuować wykonywanie kodu.

Będąc w odpowiedniej perspektywie

W celu rozpoczęcia procesu debugowania potrzebne są jeszcze tzw. punkty wstrzymania (ang. breakpoints) ustawione (przez podwójny klik na bocznym pasku przy linijce, na której taki punkt ma zostać stworzony lub przez ustawienie kursora na tejże linijce i wciśnięcie skrótu [Ctrl+Shift+B]) na ścieżce wykonywania się programu. Gdy uruchomimy aplikację w trybie odpluskwiania i natrafimy na któryś z punktów wstrzymania to Eclipse IDE zapyta się nas czy chcemy się przełączyć do perspektywy Debug. Odpowiadając pozytywnie powinniśmy zobaczyć zestaw widoków przeznaczonych do wydajnego odpluskwiania kodu. Rysunek 2. przedstawia przykładowy wygląd perspektywy Debug.

Najważniejsze widoki to:

- Debug - pozwala zobaczyć jaki jest stos wywołania metod w momencie zatrzymania wykonywania kodu. Możemy również cofnąć się do którejś z wcześniej wywołanych metod, aby zobaczyć jakie wartości miały zmienne w momencie wywołania kolejnej metody. Możemy również przejść do kolejnej linijki kodu (przycisk Step Over), wejść do kolejnej wywoływanej metody (przycisk Step into), wyjść z aktualne wykonywanej metody (przycisk Step return), kontynuować normalne wykonywania (przycisk Resume), lub też przerwać wykonywanie (przycisk Terminate).

- Variables – pozwala sprawdzać oraz edytować wartości (opcja Change Value... z menu kontekstowego) pól klas oraz zmiennych dostępnych w danym bloku kodu. Po kliknięciu na danej zmiennej (lub polu) wyświetli się jej wartość (dla typu prostego) lub wartość metody toString (dla obiektu).

Zrzut ekranu
przedstawiający perspektywę Debug

Rysunek 2. Zrzut ekranu przedstawiający perspektywę Debug

- Breakpoints – pozwala zarządzać wszystkimi zdefiniowanymi punktami wstrzymania oraz pozwala dodawać nowe. Więcej informacji o punktach wstrzymań w dalszej części artykułu.

- Expressions – umożliwia obserwowanie wartości przez siebie zdefiniowanych wyrażeń opartych na polach klas lub zmiennych. Aby dodać nowe wyrażenie wystarczy zaznaczyć je w kodzie (np. nazwę zmiennej) kliknąć prawym przyciskiem myszy na edytorze i z menu kontekstowego wybrać opcję Watch. Można to zrobić również klikając prawym przyciskiem w polu widoku i wybierając opcję Add Watch Expression, a następnie wpisując interesujące nas wyrażenie.

Punkty wstrzymań

Jak już zostało wspomniane w celu odpluskwiania kodu potrzebne są odpowiednio ustawione punkty wstrzymań. Każdy taki punkt ma swoje właściwości, do których można się dostać klikając prawym przyciskiem na danym punkcie (na bocznym pasku przy kodzie lub w widoku Breakponts) i wybierając opcję Breakpoint properties…. Dla każdego punktu wstrzymań można ustawić wartość Hit Count, która mówi ile razy dany punkt musi zostać osiągnięty, aby wykonywanie kodu zostało wstrzymane. Pozostałe właściwości punktów wstrzymań różnią się w zależności od ich rodzaju. Eclipse IDE oferuje pięć różnych rodzajów punktów wstrzymań:

- dla linii – standardowe, dotyczące jednej konkretnej linii kodu

- dla metody – aktywne przy wejściu/wyjściu do/z metody (do ustawienia we właściwościach – odpowiednio: Method Entry i Method Exit). Możliwe jest również ustawienie punktów wstrzymań na metodach, do których nie mamy źródeł – taki punkt można stworzyć w widoku Outline (opcja Taggle Method Breakpoint w menu kontekstowym po kliknięciu prawym przyciskiem myszy na wybranej metodzie).

- dla pola (tzw. watchpoint) - aktywne przy dostępie lub modyfikacji wartości pola klasy (można to ustawić we właściwościach – odpowiednio: Field access i Field Modyfication).

- dla klasy – aktywne przy pierwszym ładowaniu danej klasy. Podobnie jak w przypadku metod można ustawić punkt wstrzymań na klasie, do której nie mamy źródeł – w tym celu również wykorzystujemy widok Outline (opcja Taggle Class Load Breakpoint w menu kontekstowym po kliknięciu prawym przyciskiem myszy na nazwie klasy).

- dla wyjątku – aktywne w momencie, gdy wybrany wyjątek jest rzucony. Aby stworzyć takiego breakpointa należy w widoku Brakpoints kliknąć przycisk Add Java Exception Breakpoint, a następnie w nowym oknie określić jaka klas wyjątku nas interesuje.

Dodatkowo dla punktów wstrzymań metod i linii można definiować warunki przy których dany punkt będzie aktywny (np. gdy chcemy się zatrzymać, gdy określona zmienna przyjmie interesującą nas wartość).

Zastępowanie kodu na gorąco

Wyobraźmy sobie sytuacje, w której debugujemy kod już drugą godzinę i w końcu dochodzimy do miejsca, w którym wydaje nam się, że znaleźliśmy błąd. Dla pewności chcielibyśmy zmienić kawałek kodu i zobaczyć, czy wszystko zadziała tak jak byśmy tego chcieli. Co musimy zrobić? Zatrzymać proces odpluskwiania, zmienić kod i rozpocząć cały proces od nowa? Z Eclipse IDE nie jest to konieczne! Pozwala on na zmianę kodu w czasie jego wykonywania. Mechanizm ten, zwany zastępowaniem kodu na gorąco (ang. hot code replace), jest bardzo przydatny aby sprawdzić szybkie rozwiązania bez potrzeby restartu i reprodukcji stanu, w którym akurat jesteśmy podczas odpluskwiania. Aby skorzystać z tego rozwiązania muszą być spełnione następujące warunki:

- Wirtualna Maszyna Javy (ang. Java Virtual Machine), z której korzystamy, wspiera zastępowanie kodu na gorąco.

- W Eclipse IDE włączony jest mechanizm automatycznej kompilacji (opcja w menu głównym Project->Build Automatically).

- Zmiana dokonana w kodzie nie może zmieniać „kształtu” klasy, czyli żadna metoda ani pole nie mogą zostać usunięte ani dodane.

Jeśli podczas zmiany kodu wystąpi błąd kompilacji to może się okazać, że jedna z ramek na stosie wywołania metod jest niepoprawna i dalsze przetwarzanie może okazać się niemożliwe.

Odpluskwianie zdalne

Eclipse IDE jest zatem potężnym narzędziem pozwalającym na analizę kodu podczas jego wykonywania. Warto się zastanawiać, czy możliwe jest przeanalizowanie aplikacji uruchomioną lokalnie, lecz poza samym Eclipse IDE lub też zupełnie zdalnie – na innym komputerze? Oczywiście Eclipse IDE pozwala również i na to! Wygląda to podobnie to odpluskwiania aplikacji lokalnych, jedynie odpluskwiana aplikacja musi być uruchomiona z odpowiednimi parametrami (parametry te czytelnik znajdzie w ramce).

Parametry uruchamiania aplikacji do odpluskwiania zdalnego.

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket, server=y, suspend=y, address=8000

-Djava.compiler=NONE

Gdy program jest uruchomiony z tymi parametrami to startuje i czeka na połączenie z narzędziem do odpluskwiania (ang. debuger). W Eclipsie IDE wybieramy z menu głównego Debug->Open Debug Dialog następnie tworzymy nową instancję Remote Java Aplication specyfikujemy adres pod jakim dostępna jest zdalna aplikacja oraz odpowiedni port (wartość parametru address z jakim została aplikacja uruchomiona, np. 8000). Po kliknięciu przycisku Debug Eclipse IDE łączy się ze zdalnym programem i rozpoczyna sesję odpluskwiania. Kod aplikacji jest brany z aktualnej przestrzeni pracy (ang. workspace).

Co nowego w Eclipse IDE 3.3?

W wersji 3.3 Eclipse IDE pojawiło się wiele nowości. Z punktu widzenia odpluskwiania najciekawsze są trzy nowinki (wszystkie wymagają Javy SE 6). Po pierwsze Eclipse IDE umożliwia nam zobaczenie wszystkich referencji danego obiektu. Są swa sposoby dostępu do tej informacji:

- W menu widoku Variables wybieramy Java->Show References (tak jak jest to zaprezentowane na Rysunku 3.). Referencje zostaną wyświetlone jako część widoku Variables.

- W widoku Variables klikamy prawym przyciskiem na wybranej zmiennej i z menu kontekstowego wybieramy All References lub wciskamy skrót [Ctrl+Shift+R]. Pojawi się wówczas dodatkowe okienko z informacją o referencjach.

Dodawanie
widoczności referencji wybranej zmiennej

Rysunek 3. Dodawanie widoczności referencji wybranej zmiennej

Po drugie możliwe jest wyświetlenie wszystkich instancji danego typu – wystarczy tylko w edytorze kliknąć prawym przyciskiem myszy na wybranym typie lub na zmiennej w widoku Variables i z menu kontekstowego wybrać opcję All Instances, można również skorzystać ze skrótu [Ctrl + Shift + N].

Edytor z
metodą zwracającą nieodpowiadającą nam wartość

Rysunek 4. Edytor z metodą zwracającą nieodpowiadającą nam wartość

Po trzecie można wymusić wcześniejsze wyjście z metody, w której akurat zatrzymane jest przetwarzanie. Aby skorzystać z tej opcji należy zaznaczyć w edytorze wyrażenie, które ma zostać zwrócone i z menu kontekstowego wybrać pozycję Force Return. Jeśli chcemy zwrócić określoną przez nas samych wartość należy w widoku Display wpisać wartość, która ma zostać zwrócona, zaznaczyć ją, kliknąć prawym przyciskiem myszy na zaznaczeniu i z menu kontekstowego wybrać opcję Force return lub użyć skrót [Alt+Shift+F]. Przykładowo, jeśli jesteśmy akurat w metodzie zwracającej wartość int (Rysunek 4.) i zgodnie z przetwarzaniem metoda zwróciłaby wartość 1, a my chcemy tę wartość zmienić na 2 to w widoku Display wpisujemy wartość 2, zaznaczamy ją i z menu kontekstowego wybieramy odpowiednią opcję (Rysunek 5.).

Wymuszenie
zwrócenia wybranej wartości

Rysunek 5. Wymuszenie zwrócenia wybranej wartości

Podsumowanie

W artykule zostały przedstawione możliwości Eclipse IDE w zakresie analizy wykonywanego programu. Używając Eclipse IDE programista nigdy nie zostaje sam z błędem, który wkradł się do programu. Eclipse IDE stara się ułatwić żmudne szukanie błędów przy pomocy wielu użytecznych widoków, różnorakich rodzajów punktów wstrzymań, mechanizmu zastępowania kodu na gorąco, a także odpluskwiania aplikacji zdalnych.

Source: http://www.javaexpress.pl/article/show/W_walce_o_lepsza_jakosc__odpluskwianie