Це * коли-небудь добре, щоб зловити StackOverflowError на Java?


27

Раніше я думав, що це не так, але вчора мені довелося це зробити. Це програма, яка використовує Akka (реалізація акторської системи для JVM) для обробки асинхронних завдань. Один з акторів виконує деякі PDF-маніпуляції, і оскільки бібліотека баггі, вона StackOverflowErrorраз у раз помирає .

Другий аспект полягає в тому, що Akka налаштована на вимкнення всієї системи акторів, якщо виявлена ​​фатальна помилка JVM (наприклад, StackOverflowError).

Третій аспект полягає в тому, що ця акторська система вбудована у веб-додаток (для WTF-ish, спадщини, причин), тому коли система акторів не працює, веб-додаток не є. Чистий ефект полягає в тому, що в StackOverflowErrorнашому додатку для обробки роботи стає просто порожнім веб-додатком.

Як швидке виправлення, мені довелося зловити StackOverflowErrorкинутого, щоб пул ниток акторської системи не був зірваний. Це спонукає мене думати, що, можливо, іноді нормально ловити такі помилки, особливо в таких контекстах? Коли є обробка пулу потоків довільних завдань? На відміну від OutOfMemoryErrorI, я не уявляю, як StackOverflowErrorможна залишити програму в непослідовному стані. Після такої помилки стек очищається, тому обчислення можуть тривати нормально. Але, можливо, я пропускаю щось важливе.

Крім того, зауважте, що я все для виправлення помилки, в першу чергу (фактично я вже виправив ДП в цьому ж додатку кілька днів тому), але я дійсно не знаю, коли це може виникнути така ситуація.

Чому краще було б перезапустити процес JVM, а не ловити StackOverflowError, позначити цю роботу як невдалу та продовжувати свою справу?

Чи є якась вагома причина ніколи не виловлювати ДП? За винятком "найкращих практик", це невиразний термін, який мені нічого не говорить.


1
Іншим варіантом було б збільшити простір стеків, доступний на JVM
храповик урод

3
@ratchetfreak: StackOverflowExceptions, як правило, пояснюється ланцюгом викликів методів, що не припиняються, - збільшення простору стеку тоді збільшує вартість пам'яті нового потоку без користі.
Джомінал

1
Принаймні одне ДП було законним, оскільки вхід був дуже великий. На жаль, поводження з ним з рекурсивною реалізацією (зворотний потік Java) було не дуже хорошою ідеєю. У будь-якому випадку, навіть коли обчислення гарантовано закінчено, ви не знаєте, чи новий розмір стека достатньо великий для інших обчислень.
Ionuț G. Stan

2
Чи не слід це мігрувати до Ста ... Ой, чекай ... неважливо. :-)
Blrfl

Щодо вашої бібліотеки баггі. Вам слід дійсно перенести цю функцію, що керує PDF, у свій процес, щоб ви могли дозволити OS вбити її.
Есбен Сков Педерсен

Відповіді:


44

Як правило, якби абсолютно ніколи, ніколи не було прийнятним щось робити, і щодо цього існувала згода, реалізатори мови цього не допустили б. Таких одностайно чітких сентенцій майже немає. (На щастя, адже саме це утримує нас людських програмістів на робочих місцях!)

Це виглядає так само, як ніби ви знайшли ситуацію, коли виявлення цієї помилки є найкращим варіантом для вас: вона дозволяє вашій програмі працювати, тоді як всі інші альтернативи цього не роблять, і ось що враховується в підсумку. Усі "найкращі практики" - це просто підсумки багаторічного досвіду з багатьма випадками, які зазвичай можуть бути використані замість детального аналізу конкретного випадку для економії часу; у вашому випадку ви вже зробили конкретний аналіз і отримали інший результат. Вітаємо, ти здатний до самостійної думки!

(Отож, напевно, бувають ситуації, коли переповнення стека може залишити додаток непослідовним так само, як виснаження пам'яті. Просто уявіть, що якийсь об'єкт побудований та потім ініціалізований за допомогою вкладених внутрішніх викликів методів - якщо один з них кидає, об'єкт може бути в такому стані, який не повинен бути можливим, як якщо б розподіл не вдався. Але це не означає, що ваше рішення все ще не могло бути найкращим.)


3
Спасибі. Мої сумніви були дещо підкріплені після того, як я дізнався, що .NET зробив StackOverflowExceptionвиняток, що не підлягає застосуванню. Я знаю, це інша платформа, але я подумав, що вони могли мати причину. Крім того, ваша точка щодо ініціалізації об'єкта - це місце. Це змушує мене думати, що я повинен спіймати це ДП на кілька шарів абстракції внизу, так що я не вловлю "неправильне" ДП.
Ionuț G. Stan

14
+1: найкращі практики завжди повинні пояснювати, чому і в якому контексті вони "найкращі", щоб можна було судити, чи стосуються вони вашої конкретної справи.
Майкл Боргвардт

situations hereповинно бути situations where.
Сервіс

2

Я не знаю, чи є якісь специфічні для JVM ризики, але в цілому це здається досить розумним.

Наприклад, існують рекурсивні алгоритми, як, наприклад, наївний кваксор, які мають log(n)типову глибину стека, але в гіршому випадку вони погіршуються на глибину, nщо може підірвати стек.

Найгірший випадок рідкісний, і навряд чи це повториться, якщо ви перезапустите сортування на частково відсортованому наборі, тому має багато сенсу виловити виняток переповнення стека, коли це трапиться, і перезапустити роботу, а не намагатися запобігти виникненню помилок або вбивству. весь додаток.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.