Kiedyś myślałem, że tak nie jest, ale wczoraj musiałem to zrobić. Jest to aplikacja korzystająca z Akka (implementacja systemu aktorów dla JVM) do przetwarzania zadań asynchronicznych. Jeden z aktorów wykonuje pewne manipulacje PDF, a ponieważ biblioteka jest błędna, umiera StackOverflowError
co jakiś czas.
Drugi aspekt polega na tym, że Akka jest skonfigurowane do zamykania całego systemu aktorów, jeśli zostanie wykryty błąd krytyczny JVM (np. StackOverflowError).
Trzecim aspektem jest to, że ten system aktorów jest osadzony w aplikacji internetowej (z powodu WTF, dziedzictwa, powodów), więc gdy system aktorów jest zamknięty, aplikacja internetowa nie. W efekcie StackOverflowError
nasza aplikacja do przetwarzania zadań staje się pustą aplikacją internetową.
Jako szybką poprawkę musiałem złapać StackOverflowError
rzucanego, aby pula wątków systemu aktorów nie została zerwana. Doprowadziło mnie to do wniosku, że może czasem dobrze jest wyłapać takie błędy, szczególnie w takich kontekstach? Kiedy pula wątków przetwarza dowolne zadania? W przeciwieństwie do OutOfMemoryError
nie mogę sobie wyobrazić, jak a StackOverflowError
może pozostawić aplikację w niespójnym stanie. Stos jest usuwany po takim błędzie, więc obliczenia mogą przebiegać normalnie. Ale może brakuje mi czegoś ważnego.
Pamiętajmy też, że przede wszystkim jestem za naprawieniem błędu (tak naprawdę kilka dni temu naprawiłem już SOE w tej samej aplikacji), ale tak naprawdę nie wiem, kiedy to może powstać taka sytuacja.
Dlaczego lepiej byłoby zrestartować proces JVM zamiast łapać StackOverflowError
, oznaczyć to zadanie jako nieudane i kontynuować moją działalność?
Czy jest jakiś ważny powód, aby nigdy nie łapać SOE? Z wyjątkiem „najlepszych praktyk”, które są niejasnym terminem, który nic mi nie mówi.
StackOverflowException
s są zwykle spowodowane nie kończącym się łańcuchem wywołań metod - zwiększenie przestrzeni stosu zwiększyłoby wówczas koszt pamięci nowego wątku bez żadnej korzyści.
:-)