Убить застрявший поток на работающей виртуальной машине (JBoss Instance) в Java? - PullRequest
7 голосов
/ 21 января 2011

Ошибка в сторонней библиотеке вызывает бесконечный цикл в рабочем потоке на моем экземпляре JBoss. Знаете ли вы, как убить этот «зависший» поток без перезагрузки сервера? Мы хотели бы иметь возможность восстановиться после этого, пока не будет развернуто исправление, желательно без перезагрузки.

Я видел, как несколько человек упоминали об использовании Thread.interrupt () - если бы я должен был написать свой собственный MBean, как бы я получил дескриптор рассматриваемого потока для его прерывания?

Обновление: Не удалось решить ни одним из этих методов. Я наткнулся на другую ветку о той же проблеме , в которой была ссылка, почему Thread.stop () устарела . Кто-то еще задал похожий вопрос с похожими результатами. Кажется, что более сложные контейнеры должны обеспечивать такой механизм работоспособности, но я думаю, что их руки связаны с JVM.

Ответы [ 4 ]

2 голосов
/ 21 января 2011

У меня была похожая ошибка (бесконечный цикл) в сторонней lib. Я закончил тем, что применил исправление самостоятельно (ожидая, пока люди из сторонней библиотеки исправят их беспорядок), а затем поместил измененный .class в свой .war , убедившись, что он загружается до фальшивого .class (фальшивый внутри фальшивой третьей стороны .jar ).

Это нехорошо, но работает, смотри мой вопрос здесь:

Порядок загрузки классов из файла .war

Я имею в виду следующее: если вам нужно подождать, пока люди, ответственные за стороннюю библиотеку с ошибками, исправят свои проблемы, вы можете ожидать очень долгое время. Мы не могли себе этого позволить. Нам нужно исправить как можно скорее. Поэтому мы в итоге применили патч / хак к их коду.

Например, вы можете добавить логическую проверку внутри бесконечного цикла, а затем принудительно завершить цикл, если хотите, чтобы фиктивный поток «умер».

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

2 голосов
/ 21 января 2011

Полагаю, самая сложная часть - это определить висящую нить. Вы не предоставляете информацию об этом, но, возможно, вы можете построить некоторые правила вокруг имени потока или его текущей трассировки стека.

Если вы можете идентифицировать поток по его имени, я бы получил все потоки в ВМ, получив собственную группу потоков с Thread.currentThread().getThreadGroup(), а затем поднялся бы по иерархии групп потоков, вызывая getParent() в группе потоков, пока возвращает null. Теперь у вас есть группа потоков верхнего уровня. Теперь вы можете заполнить предварительно выделенный массив всеми потоками, используя метод enumerate(Thread[] list) в группе потоков верхнего уровня.

Если вам все равно нужны трассировки стека для идентификации потока, вы также можете использовать метод статической утилиты Map<Thread,StackTraceElement[]> Thread.getAllStackTraces(), чтобы получить все потоки. Однако вычисление трассировки стека довольно дорого, так что это может быть не лучшим решением, если вы на самом деле не нужны.

После идентификации потока вы должны вызвать для него метод stop(). Прерывание не поможет, если реализация работающего кода фактически не оценивает флаг прерывания потока и ведет себя так, как вы ожидаете. Нельзя сказать, что метод stop() устарел и что его использование может иметь много забавных побочных эффектов. Вы можете найти более подробную информацию в документации API.

1 голос
/ 21 января 2011

Вы можете использовать обескураженный метод myThread.stop ().Но тогда вполне вероятно, что на Нить все еще ссылаются, так что вы должны использовать магию отражения, чтобы удалить все ссылки на эту нить из компонентов, ее удерживающих.Используйте Thread.getThreadGroup () и ThreadGroup.getThreadGroup (), чтобы перейти к корневому ThreadGroup (), а затем используйте функции iterate (), чтобы пройти через все потоки.

0 голосов
/ 05 ноября 2013

Попробуйте мой jkillthread , который пытается сделать что-то вроде этого.

...