Излишнее продвижение объектов Java в старое поколение сразу после незначительного gc, вызывающего проблемы фрагментации памяти
Мы столкнулись со странной проблемой утечки памяти в нашем приложении.
Конфигурация ГХ: ParNew + CMS
Определенный тип объектов слишком рано переводится в старое поколение и вызывает серьезные проблемы с фрагментацией.
- У выжившего было достаточно места для размещения этих предметов.
- Порог выдержки составляет 15 циклов, на основании чего преждевременного продвижения по службе не произошло.
Об этих объектах: это прокси-объекты, созданные с использованием вспомогательной библиотеки Java.
Из-за ненужного продвижения таких объектов Старое поколение слишком быстро загрязняется и происходит сильная фрагментация.
Наши наблюдения:
- Объект выделяется только в eden. Нет проблем, связанных с размером.
- Объем объекта очень мал, и он подходит для сборки мусора в следующем второстепенном gc.
- Чтобы гарантировать это, мы напечатали несколько логгеров в finalize() и заметили, что область действия заканчивается сразу после запроса. Сразу после первого второстепенного сборщика мусора.
Примечание: finalize() добавлен только для отслеживания. Даже без finalize() продвижение старого поколения происходит.
- После единственного второстепенного gc:
- ожидается, что объект будет очищен.
- Но объект продвигается к старому поколению. С помощью множественных дампов кучи мы можем отследить продвижение объекта до старого поколения.
- Все такие объекты накапливаются в старом поколении и собираются сборщиком мусора старого поколения.
- Такое поведение наблюдается только на производственных серверах и не воспроизводится в тестовых средах.
Пожалуйста, предложите, как действовать дальше, и исправить это.