Есть ли способ обхода утечки памяти Google Guava r15 (ссылка на отчет об ошибке) в компоненте кэша?
(Не полагаясь на то, что сервер приложений может очищать вещи и/или считая, что веб-приложение никогда не будет перезапущено/перераспределено)
Есть ли способ обхода утечки памяти Google Guava r15 (ссылка на отчет об ошибке) в компоненте кэша?
(Не полагаясь на то, что сервер приложений может очищать вещи и/или считая, что веб-приложение никогда не будет перезапущено/перераспределено)
Я думаю, вам не нужно заботиться об этом. В сообщении Tomcat говорится
Темы будут обновляться с течением времени, чтобы избежать вероятной утечки памяти.
IIUIC означает, что после того, как все старые потоки исчезнут, так будут все указатели на старую версию вашего класса.
Подробности: причиной пула потоков является большая стоимость создания потоков. Сам пул взломан, поскольку вы получаете поток, который делал что-то еще, и нить не является апатридом. Создание темы дорого, предполагая, что вам нужно много их и никогда не перерабатывать. Нет ничего плохого в обновлении всех потоков каждые несколько минут, поэтому я надеялся, что временное решение Tomcat прекрасно его решает. Но это не так.
Кажется, что веб-приложения, использующие кешву, могут столкнуться с утечкой памяти. После нескольких повторных развертываний контейнер приложения сбой или сбой с помощью OutOfMemoryError.
Я думал, что Tomcat может легко его решить, но по какой-то причине это не так. Так что, боюсь, вы сами должны очистить ThreadLocal
. Это легко возможно через отражение, соответствующие поля Thread.threadLocals
и, возможно, inheritableThreadLocals
. Это плохой взлом, и более сложная часть заключается в том, чтобы это произошло, когда ничто не пошло не так, т.е. Когда приложение не загружено.
Я думаю, что безопасно делать что-то вроде
Stripped64.threadHashCode = new ThreadHashCode();
поскольку содержащиеся в нем вещи необходимы только для производительности при сильных конфликтах, и они воссоздаются при использовании. Но в соответствии с комментарием MRalwasser, это не поможет вообще, так как живые потоки все равно будут ссылаться на старую ценность. Так что, похоже, нет способа.
Как ThreadLocal
работает, сохраняя данные с потоками (а не используя реальный Map<Thread, Something>
), вам придется пройти через все потоки и удалять ссылки там. Обманывание частных полей других потоков - ужасная идея, поскольку они не являются потокобезопасными, а также из-за проблем с видимостью.
Другая вещь, которая может или не работает, - это мое предложение на странице . Это всего лишь 20-строчный патч. Или просто подождите, проблема была назначена вчера.
Местные жители, которые не используются, не могут вызвать никаких проблем. AFAIK единственным использованием этого TL является статистика кеша. Поэтому избегайте загрузки CacheBuilder.recordStats
и Cache.stats
и Stripped64
.
Похоже, он окончательно закрепится. Из issue:
Дуг исправил это восходящее направление для нас, и мы заправили его обратно в Гуаву: http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.9
На первый взгляд его изменение кажется идентичным mine.
Наконец, это было отмечено как фиксированное, и было объявлено Guava 18.0-rc1. Было просто грустно, что это заняло много времени, учитывая, что изменение совпадает с моим (9 месяцев назад).
Вы можете использовать ServletListener ClassLoaderLeakPreventor https://github.com/mjiderhamn/classloader-leak-prevention/, который также очищает ThreadLocals от undeploy/stop. Он также имеет исправления/обходные пути для других распространенных утечек.
Кажется, это недостаток ThreadLocals. Вы получите то же самое каждый раз, когда кладете класс уровня приложения в ThreadLocal.
Единственным обходным решением является перезапуск сервера при развертывании, я думаю. Я думаю, что это известная проблема Java-приложений. Вы уверены, что это единственное место, которое перестает выгружать загрузчик классов?