Image

Categories:

Насколько безопасно перехватывать OutOfMemoryError?

В учебниках пишут, что Error-ы никогда не следует перехватывать. Однако так вышло, что мне нужно перехватить OutOfMemoryError в совершенно универсальном математическом алгоритме.

Кратко опишу. У меня есть некие две функции p(P,n) и q(P,n), получающие на входе точечное множество P и целое число n и возвращающие на выходе другое точечное множество, состоящее, приблизительно, из |P|*n2 точек (|P| - число точек в P). Обычно эти две функции возвращают одно и то же множество, но бывают исключения. Вторая фунция (и, что куда важнее, некоторые долгоиграющие родственные алгоритмы) работает намного быстрее, особенно для больших n. Поэтому я написал универсальный библиотечный метод, тестирующий равенство p(P,n)=q(P,n) для n=1,2,... и определяющий как можно большее n (чем больше, тем лучше), при котором равенство еще имеет место.

Мое множество точек - это попросту HashSet, а точка - некий хранящийся в нем маленький объект. Очевидно, при вычислении множеств p(P,n) и q(P,n) может произойти переполнение памяти (если я попытаюсь проверять "слишком большие" n, когда число точек |P|*n2 измеряется десятками миллионов). Предсказать заранее это довольно трудно - все зависит от исходного P и объема свободной памяти. Алгоритмы вычисления p(P,n) и q(P,n) работают достаточно быстро, чтобы переполнить гигабайт памяти за десяток секунд.

С точки зрения логики, ничего страшного в OutOfMemoryError здесь нет. Самая правильная реакция - просто прекратить расчет и вернуть последнее проверенное число n. Проверяемые множества p(P,n) и q(P,n) (HashSet-ы) хранятся в локальных переменных, которые сразу станут "мусором" после завершения метода. Будь это Паскаль или C, я бы не "напрягался".

Но безопасен ли перехват OutOfMemoryError в Java? Можно ли считать, что если, перехватив эту ошибку, я просто выйду из метода и "забуду" свои сверхбольшие HashSet, переполнившие память, то система гарантированно нормально продолжит работу (разве что "затормозит")? Или все же появление OutOfMemory, как и прочие Error-ы, есть катастрофическая ситуация, о которой непременно следует сообщить вызывающему приложению и пользователю?