Определить, кто создал тему (с. Затмение) - PullRequest
21 голосов
/ 04 августа 2009

Как я могу узнать, кто создал тему в Java?

Представьте себе следующее: вы используете ~ 30 сторонних JAR-файлов в сложной среде плагина. Вы запускаете его, запускаете много кода, выполняете некоторые вычисления и, наконец, вызываете shutdown ().

Этот жизненный цикл обычно работает нормально, за исключением того, что при каждом запуске некоторые (не демонические) потоки остаются висящими. Это не было бы проблемой, если бы каждое завершение было последним выключением, я мог бы просто запустить System.exit () в этом случае. Однако этот цикл может выполняться несколько раз, и он производит больше мусора за каждый проход.

Итак, что мне делать? Я вижу темы в представлении отладки Eclipse. Я вижу их следы стека, но они не содержат никаких намеков на их происхождение. Нет трассировки стека создателя, нет различимого имени класса, ничего.

У кого-нибудь есть идеи, как решить эту проблему?

Ответы [ 4 ]

14 голосов
/ 04 августа 2009

Хорошо, я смог решить (вроде) проблему самостоятельно: я поставил точку останова в

Thread.start() 

и вручную проходил через каждый вызов. Таким образом, я довольно быстро обнаружил, что Class.forName () инициализирует много статического кода, который в свою очередь создает эти таинственные потоки.

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

10 голосов
/ 04 августа 2009

Я неукоснительно называю свои потоки (используя Thread (например, Runnable, String) ), в противном случае они заканчиваются общим и несколько бесполезным именем. Сброс потоков будет подсвечивать то, что работает и (таким образом), что их создало. Я не ценю создание сторонних потоков.

РЕДАКТИРОВАТЬ: бюллетень JavaSpecialist недавно обратился к этой проблеме (февраль 2015 года) с помощью диспетчера безопасности. Подробнее см.

БОЛЬШЕ: Несколько деталей по использованию техники JavaSpecialist: API SecurityManager включает в себя «checkAccess (newThreadBeingCreated)», который вызывается в потоке создателя потока. Новый поток уже имеет инициализированное имя. Таким образом, в этом методе у вас есть доступ как к потоку создателя потока, так и к новому, и вы можете записывать / распечатывать и т. Д. Когда я попробовал это, отслеживаемый код начал генерировать исключения защиты доступа; Я исправил это, вызвав его в AccessController.doPriviledged (новый PrivilegedAction () {...}, где метод run () вызвал отслеживаемый код.

1 голос
/ 04 августа 2009

При отладке приложения Eclipse вы можете остановить все потоки, щелкнув поле org.eclipse.equinox.launcher.Main в представлении отладки.

Затем оттуда для каждого потока вы можете увидеть трассировку стека и перейти к методу thred run.

Иногда это может помочь, а иногда нет.

Как сказал Брайан, хорошей практикой является именование потоков, поскольку это единственный способ легко определить, "кто их создал"

0 голосов
/ 04 августа 2009

К сожалению, это не так. В Eclipse я вижу все блокирующие потоки, но их трассировки стека отражают только их внутреннее состояние и (по-видимому) не раскрывают информацию о месте их создания. Также из взгляда внутрь объекта (с использованием представления Variables) я не смог выявить дальнейшие подсказки.

...