Стоит ли очищать ThreadLocals в фильтре для решения проблем, связанных с пулом потоков?

Вкратце - tomcat использует пул потоков, поэтому потоки повторно используются. Некоторые библиотеки используют переменные ThreadLocal, но не очищают их (используя .remove()), поэтому на самом деле они возвращают "грязные" потоки в пул.

Tomcat имеет новые функции обнаружения этих вещей при выключении и очистки локаторов потоков. Но это означает, что потоки "грязны" во время всего выполнения.

Что я могу сделать, это реализовать Filter, и сразу после завершения запроса (и поток возвращается в пул) очистите все ThreadLocal s, используя code from tomcat (метод называется checkThreadLocalsForLeaks).

Вопрос в том, стоит ли это? Два плюса:

  • предотвращение утечки памяти
  • предотвращение неопределенного поведения библиотеками, которые предполагают, что поток "свежий"

Один символ:

  • Решение использует отражение, поэтому оно потенциально замедляется. Все данные отражения (Field s) будут, конечно, кэшированы, но все же.

Другой вариант - сообщить об этой проблеме в библиотеки, которые не очищают локаторы потоков.

Ответы

Ответ 1

Я бы рассмотрел маршрут сообщения о проблеме разработчикам библиотеки по двум причинам:

  • Это поможет другим людям, которые хотят использовать одну и ту же библиотеку, но не имеют навыков/времени, чтобы найти такую ​​УЖАСНУЮ утечку памяти.
  • Чтобы разработчики библиотеки могли создавать лучший продукт.

Честно говоря, я никогда раньше не видел такого типа ошибок, и я думаю, что это исключение, а не то, что мы должны охранять, как это часто бывает. Не могли бы вы поделиться с какой библиотекой вы видели это поведение?

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

Ответ 2

в теории, это кажется хорошей идеей. однако я мог видеть некоторые ситуации, когда вы, возможно, не захотите этого делать. например, некоторые из связанных с xml технологий имеют некоторые нетривиальные затраты на установку (например, создание DocumentBuilders и Transformers). если вы много чего делаете в своем webapp, может иметь смысл кэшировать эти экземпляры в ThreadLocals (поскольку утилит обычно не являются потокобезопасными). в этом случае вы, вероятно, не хотите очищать их между запросами.

Ответ 3

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

Использование threadlocals может быть неправильным поведением библиотеки, и вы должны обязательно сообщать об этом авторам, но, к сожалению, прямо сейчас вам решать, как это сделать.

Я бы не слишком беспокоился о производительности. Медленный бит в отражении - это поиск метаданных; как только у вас есть объект Field, то его использование довольно быстро и с течением времени становится быстрее - AIUI, он начинает работать, создавая собственный вызов в JVM, но после некоторого количества применений он генерирует байт-код для доступа, который затем может быть скомпилирован в собственный код, оптимизирован, встроен и т.д., поэтому он не должен быть намного медленнее, чем прямой доступ к полям. Я не думаю, что код Tomcat повторно использует объекты Field во всех запросах, поэтому, если вы хотите воспользоваться этим, вам придется написать свой собственный код очистки. В любом случае, стоимость исполнения будет намного меньше стоимости IO, связанной с запросом.