использование статического словаря в качестве кеша может привести к утечке?

У меня есть утечка памяти в веб-приложении (сервлете), над которым я работаю. Я с подозрением отношусь к 1 причине и хотел бы услышать ваши идеи по этому поводу.

Я использую хэш-карты, хэш-наборы и т. Д. В качестве БД (загружено около 20 МБ данных). Эти карты, наборы перезагружаются раз в 10 минут. Огромное количество одновременных запросов. Я читал, что GC передает объекты, которые не собираются в течение периода времени/цикла, в поколение (старое и постоянное поколения), которое меньше проверяется или собирается мусор. Я думаю, что мое использование статических карт и наборов вызывает у меня проблемы с утечкой. Что вы думаете ?


person WorM    schedule 21.07.2010    source источник
comment
Прежде всего спасибо за ответы. Я буду иметь в виду ваши предложения. Вот еще некоторые подробности; Каждые десять минут я выполняю следующие шаги: 1) Я создаю новые карты (как временные карты) в фоновом режиме. 2) Очистите старые карты с помощью вызова метода .clear() (даже присвойте им значение null, прежде чем переходить к шагу 3) 3) Дайте ссылку на новые карты на старые карты. Могу ли я что-то пропустить здесь?   -  person WorM    schedule 21.07.2010
comment
Как элементы вашего кода, которые обращаются к этим картам, фактически получают доступ к содержимому? Вы уверены, что никакой другой элемент кода не захватывает ссылку на саму статическую карту? Хранение данных приложения в статической переменной — это что-то вроде запаха кода и может очень просто привести к проблемам с утечкой, если не будет хорошо спроектировано.   -  person matt b    schedule 21.07.2010


Ответы (5)


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

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

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

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

person nojo    schedule 21.07.2010

Как заметил Ромен, статическая карта вызывает подозрения. Если по какой-то причине вы не можете регулярно явно очищать его, вы можете рассмотреть возможность использования WeakHashMap, что

Реализация Map на основе хеш-таблиц с слабыми ключами. Запись в WeakHashMap будет автоматически удалена, когда ее ключ больше не используется в обычном режиме. Точнее, наличие сопоставления для данного ключа не помешает сборщику мусора отбросить ключ, то есть сделать его финализируемым, финализируемым, а затем повторно востребованным. Когда ключ отбрасывается, его запись фактически удаляется из карты, поэтому этот класс ведет себя несколько иначе, чем другие реализации Map.

К сожалению, для Java6 в стандартной библиотеке отсутствует WeakHashSet, но в сети можно найти несколько реализаций.

person Péter Török    schedule 21.07.2010

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

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

person Romain Hippeau    schedule 21.07.2010

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

person pdbartlett    schedule 21.07.2010

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

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

person Eyal Schneider    schedule 21.07.2010