Java HR: Czy kod w bloku finally zawsze się wykona?

Java HR: Czy kod w bloku finally zawsze się wykona?

To pytanie raczej z kategorii tych podchwytliwych niż testujących znajomość Javy, niemniej jednak spotkałem się już z nim kilkukrotnie w czasie rozmów rekrutacyjnych, więc lepiej być na nie przygotowanym.
Brzmi ono – czy kod w bloku finally wykona się zawsze? (Więcej o finally w tym artykule – Java HR: final, finally i finalize.)


Pierwsze skojarzenie, jakie przychodzi zwykle to głowy to „Oczywiście, przecież właśnie po to jest – żeby wykonać się zawsze, niezależnie od tego co stanie się w bloku trycatch.” O ile z punktu widzenia założeń i specyfikacji języka, jest to stwierdzenie jak najbardziej poprawne, to niestety prawdziwa odpowiedź na postawione pytanie nie jest już tak oczywista.
Czy programista oczekuje, że kod wykona się zawsze? Tak. Czy JVM zatroszczy się o to, żeby kod wykonał się zawsze? Tak.
Wobec tego, czy wykona się zawsze? Niekoniecznie.

Tak naprawdę istnieje szereg przypadków, gdy nie uda się tego dokonać. Niektóre z tych sytuacji sprowokować musimy sami, inne mogą wystąpić wbrew naszej woli. Oto one:
  • Nieskończona pętla w try lub catch – jeden z najprostszych i najbardziej oczywistych przypadków, jednak łatwo jest o tym zapomnieć i oczekiwać, że konstrukcja try-finally ochroni nas przed każdym błędnie napisanym kodem, nieważne co się wewnątrz bloku try wydarzy. Kod w finally nie będzie miał jednak okazji się w takim wypadku wykonać.
  • Deadlock – podobna sytuacja będzie miała miejsce, gdy wątki wzajemnie będą się blokować, wstrzymując tym samym wykonanie programu na zawsze.
  • System.exit() – tu już trudniej o pomyłkę, ponieważ bezpośrednio i wymownie zlecamy zakończenie działania programu. Nie powinno więc dziwić, że kod w finally nie zostanie w takiej sytuacji wykonany.
  • finally w demonie – należy pamiętać, że działanie demonów może zostać przerwane w każdym momencie, jeśli skończą się wszystkie pozostałe zwyczajne wątki.
  • Błąd maszyny wirtualnej JVM – niestety nic nie jest idealne i może zdarzyć się, że JVM po prostu wysypie się, nie z naszej winy.
  • Przerwanie działania JVM przez system – może to być polecenie kill -9 czy ubicie procesu z poziomu Menedżera Zadań w Windowsie. Jakiekolwiek zatrzymanie programu z zewnątrz (przez system) spowoduje, że kod w finally nie będzie miał okazji się wykonać.
  • System operacyjny przestaje działać – z powodów takich jak:
    • błąd systemu
    • awaria prądu
    • wyłączenie komputera przez użytkownika
    • koniec świata

    Bez systemu i sprzętu, na których powinien być uruchomiony program, kod także nie zostanie wykonany.

Mnogość tych przykładów pokazuje, że pewne są tylko śmierć i podatki, a finally niestety już nie. (Czego innego możemy się spodziewać wyłączając komputer w trakcie działania programu?).
Jednakże zakładając że program ma warunki, żeby móc wykonać się normalnie, a kod pozbawiony jest rażących błędów, możemy spodziewać się że kod w finally wykona się zawsze.

Należy pamiętać, że używając instrukcji sterujące (takie jak return, continue, break) w bloku try, nie wywołamy takiego efektu. Kod zawarty w finally wykona się mimo wszystko, wywołując wspomniane przekierowania dopiero na koniec.

Informatyk, programista. Obecnie Java Developer (Web Fullstack), właściciel studia Berrygames oraz prezes koła TK Games na Politechnice Wrocławskiej.

Wszystkie artykuły autora>>

Dodaj komentarz