Co to jest i jak czytać StackTrace?

Wiesz już, czym są wyjątki w Java, wiesz też jak je rzucać… ale czy wiesz jak je interpretować? W szczególności jak czytać StackTrace, który zawsze towarzyszy wyjątkowi?

Wśród programistów krąży powiedzenie, że kod jest czytany więcej razy niż pisany (dlatego musi być napisany w prosty i zrozumiały sposób). Podobnie jest z wyjątkami, częściej będziesz je czytał niż, rzucał w swojej aplikacji. Dlatego też warto nauczyć się je czytać zawczasu i nie domyślać się “co tak naprawdę to znaczy”.

Zanim zapoznasz się z samym StackTrace’em warto, żebyś wiedział, że stuktura danych, na której on bazuje, zwana jest stosem (ang. stack). Opisałem ją dokładnie w tym wpisie.

Można powiedzieć, że StackTrace to “ścieżka”, którą podążało wykonanie programu do momentu powstania błędu. Więc w StackTrace znajduje się lista wszystkich metod, które są „aktualnie” wykonywane i w takiej kolejności doprowadziły do wyjątku.

Mówiąc jeszcze inaczej, patrząc na StackTrace, będziesz widział listę metod wywołanych na poszczególnych poziomach aplikacji. Wywołania te doprowadziły do wystąpienia tego wyjątku. Co ważne, nie zobaczysz tutaj wartości zmiennych, oraz wartości atrybutów (pól) klasy.

Samo pojęcie StackTrace związane jest ze stosem wykonania, jednak w Java potocznie rozumie się przez to sam stos wykonania wraz z wyjątkiem (lub wyjątkami), w jaki jest on “opakowany”.

Javowy StackTrace, zaczyna się od nazwy wyjątku, który go spowodował. W tej samej linii znajduje się też dodatkowa informacja dołączona przez programistę. “Zazwyczaj”, gdyż sporo osób nie dołącza do wyjątku żadnej “wiadomości”. Przyśpiesza to i ułatwia programowanie, bo nie trzeba się zastanawiać co tam napisać. Jednak jest to jedyny sposób, w jaki możemy sobie sami pomóc, kiedy to przyjdzie nam analizować ten wyjątek. W tej wiadomości możemy dodać informacje o wartości lokalnych zmiennych, które wpłynęły na wystąpienie właśnie tego wyjątku. Dlatego zawsze dodawaj “wiadomość” do każdego wyjątku, jaki rzucasz.

Każda linia zaczynająca się od “at” podaje:

  • w pełni kwalifikowaną nazwę metody (czyli nazwę pakietu, klasy oraz metody),
  • nazwę pliku źródłowego (w nawiasach okrągłych) oraz,
  • po dwukropku, numer linii.

Taki zapis pozwala jednoznacznie określić miejsce w aplikacji (lub bibliotece zewnętrznej), które było aktualnie wykonywane.

Na samym dole znajduje się tzw. metoda wejściowa, w prostych aplikacjach konsolowych, będzie to zawsze metoda main(String []). Natomiast na samym końcu znajduje się metoda, w której to wystąpił wyjątek.

Zazwyczaj nazwa pakietu Twojej aplikacji będzie znajdowała się na samej górze… gdyż zazwyczaj błędy popełniamy my, a nie autorzy bibliotek, których używamy. Czasami jednak nasza nazwa pakietu znajduje się gdzieś w “środku” StackTrace, wtedy zazwyczaj oznacza to, że przekazaliśmy złe parametry do wywołania metody z danej biblioteki. Baaaardzo rzadko oznacza to błąd w bibliotece.

Przyjrzyjmy się przykładowemu wyjątkowi:

Widzimy tutaj NullPointerException w 16 linii klasy Book z pakietu pl.kursprogramisty w metodzie getTitle(). Metoda ta została wywołana przez Author.getBookTitles(), która znajduje się w pliku Author.java w linii 25. Z kolei metoda getBookTitles() wołana jest z Bootstrap.main(), z pliku Bootstrap.java w linii 14.

Jak to bywa zazwyczaj z wyjątkami typu NullPoinerException, pewnie jedno z pól (właściwości) klasy Book bądź nie zostało zainicjalizowane, bądź zostało zainicjalizowane wartością null (czyli, tak jak by w ogóle nie zostało zainicjalizowane). Takie zachowanie skutkuje właśnie takim wyjątkiem w momencie próby wykonania jakiejkolwiek metody, na której zmiennej wartość jest null.

Często widzi się w kodzie, że w bloku catch, złapany wyjątek opakowywany jest w inny typ, który jest następnie rzucany. Poniżej znajduje się przykład takiego kodu:

W takim przypadku należy rozumieć, że wyjątek MyProjectServletException został spowodowany przez (ang. caused by) ConstraintViolationException. Wtedy w StackTrace zobaczymy linię zaczynającą się od “Caused by: ConstraintViolationException”. Co może skutkować takim przykładowym StackTrace:

Przełóżmy to na trochę prostszy przykład. Załóżmy, że piszesz prosty kalkulator:

W powyższym przykładzie CalculationException spowodowany został przez AdditionException, gdyż próbujemy dodać dwie liczby, z których jedna jest spoza karesu przyjętego przez nas za obsługiwany.

To tyle, jeżeli chodzi o czytanie wyjątków ze zrozumieniem. Jeżeli coś jest jeszcze nie jasne, zapraszam do komentarzy.

3 Comments Co to jest i jak czytać StackTrace?

  1. Aleksander

    Kiedy będzie o programowaniu obiektowym lub/czy kontynuacja? Czytam kurs krok po kroku a tu nagle koniec .

    Pozdrawiam

    Reply
    1. Dariusz Łuksza

      Od jakiegoś czasu piszę tutaj głównie z doskoku, kiedy mam chwilę przerwy w innych projektach. Na chwilę obecną nie mogę powiedzieć kiedy pojawią się nowe wpisy.

      Reply
      1. Aleksander

        Dziękuje za odpowiedź. Szukam czegoś na temat programowania obiektowego bo przykłady które znajduję typu x,y celem stworzenia jakiś współrzędnych zupełnie nie ułatwiają nauki .

        Reply

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *