Java Spring: ReRun умер поток после OutOfMemoryError - PullRequest
1 голос
/ 11 февраля 2012

Я разработал приложение с помощью Spring. У меня есть bean-компонент для создания потока, но во время выполнения этого потока во время выполнения JVM выбрасывает OutOfMemoryError - Java Heap Space.
Я хотел бы спросить, подходит ли следующее решение для решения проблемы: После того, как выброшенный поток умирает и освобождает память, ранее занятую этим потоком, затем через другой поток (который я называю RestartThread) я понимаю, что поток мертв (без перехвата ошибки), затем:
1) вызвать сборщик мусора, который эффективно освобождает память от мертвого потока;
2) вызовите функцию run () прерванного потока, которая перезапускает предыдущий экземпляр (включая закрытые переменные, используемые прерванным потоком, которые остаются в памяти даже после генерации OutOfMemoryError) прерванного потока.
Что вы думаете об этой вещи, это может создать проблемы? Это правильное решение для перезапуска предыдущей версии умершей темы?

Заранее спасибо,
--Alucard

Ответы [ 3 ]

2 голосов
/ 11 февраля 2012

Восстановление из OutOfMemoryError, особенно в многопоточной среде, очень сложно, а часто даже невозможно. Вы, вероятно, должны выяснить, почему у вас заканчивается память (например, из-за утечек ссылок или вашему приложению просто нужно больше памяти, чем вы отдали), и попытаться исправить ее, а не пытаться восстановить ее.

Даже если бы вы могли просто позволить потоку, выдавшему ошибку, умереть и перезапустить ее, перезапущенный поток, вероятно, просто умрет снова в самом начале. В более худшем сценарии основная причина может быть в какой-то другой части программы. Это будет означать, что другие потоки в вашем приложении начнут выдавать ту же ошибку, так как они будут пытаться выделить новые объекты, что приведет к каскадной ошибке во всем приложении, и, в конечном итоге, все произойдет потрясающе.

Память не единственная ваша проблема. Состояние вашего приложения может быть почти любым (то есть несовместимым), если поток, завершенный OOME, находился в середине обработки и касался состояния (состояний) некоторых общих объектов, которые также используют другие потоки. Кроме того, если другой поток ожидает какой-либо монитор (мьютекс), который удерживает завершенный поток, или что-то подобное (ожидание / уведомление и т. Д.), Другой поток может оказаться заблокированным. В большинстве случаев написать логику восстановления и проверить, что восстановление прошло успешно, будет очень сложно, поскольку слишком много переменных и вещей нужно проверить, прежде чем можно будет быть уверенным, что приложение действительно ДЕЙСТВИТЕЛЬНО восстановлено.

2 голосов
/ 11 февраля 2012

Сделайте все, чтобы предотвратить OutOfMemoryError. Он генерируется JVM, когда у него нет другого выбора, т. Е. Все объекты, которые могут быть удалены GC, уже удалены. Когда это происходит, у JVM часто нет ресурсов даже для изящного завершения. Это должно быть убито и начато снова. Скорее всего, даже если вы попытаетесь перехватить OutOfMemoryError и отсоединить некоторые ресурсы, это не сработает и, по крайней мере, не будет работать надежно.

1 голос
/ 12 февраля 2012

Вы можете попытаться понять, почему у вас возникает ошибка OOM, генерируя дамп кучи. См. Здесь:

Ссылка

Хотя ответ здесь для сервера приложений JBoss, он должен работать в общем случае для любого процесса Java.

Позже вы можете проанализировать этот дамп и, возможно, обнаружите, что генерируется много объектов одного типа.

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...