Подтвердить что ты не робот

Почему пространство PermGen растет?

Я прочитал несколько статей, и я понял следующее (пожалуйста, исправьте меня и/или отредактируйте вопрос, если я ошибаюсь):

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

  • Молодое поколение: создаваемые объекты идут сюда, эта часть часто и недорого собирает мусор

  • Старое поколение: объекты, которые выходят из сборщиков мусора молодого поколения, идут сюда, эта область собирает меньше мусора и использует более требовательный процессор/алгоритм (я считаю, что он называется mark-sweep)

Изменить: как указано другим пользователем, PermGen не является частью области с именем heap

  • PermGen: эта область заполнена метаданными классов приложений и многими другими вещами, которые не зависят от использования приложения.

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

На самом деле, если пространство PermGen растет, есть ли способ сбора мусора или reset it?

4b9b3361

Ответ 1

Собственно, в Sun JVM Permanent Generation (PermGen) полностью отделено от кучи. Вы уверены, что не смотрите на Теневое поколение? Было бы подозрительно, если бы ваше Постоянное поколение продолжало расти.

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

Если вы оказались в Solaris, вы можете использовать jmap -permstat, чтобы сбрасывать статистику по учетным данным, но этот параметр не доступен для Windows (и, возможно, других платформ). Вот документация по jmap для Java 6

Из руководства Sun на JConsole (который позволит вам просмотреть размер этих пулов):

Для виртуальной машины Java HotSpot память бассейны для серийной сборки мусора следующие.

  • Eden Space (куча): пул, из которого первоначально выделена память для большинства объектов.
  • Survivor Space (куча): пул, содержащий выжившие объекты мусорная коллекция Идена пространство.
  • Наложенное поколение (куча): пул, содержащий объекты, которые существовали в течение некоторого времени в оставшемся в живых пространстве.
  • Постоянное поколение (не куча): пул, содержащий все отражающие данные самой виртуальной машины, таких как объекты класса и метода. С Java-виртуальные машины, использующие совместное использование данных классов, это поколение делится на только для чтения и чтения-записи.
  • Кэш-код (не куча): виртуальная машина HotSpot Java также включает в себя кеш-код, содержащую память, которая используется для сбор и хранение родных код.

Ответ 2

Наиболее распространенными причинами, которые я видел, являются:

  • Пользовательские загрузчики классов, которые не загружают более старые классы после загрузки новых.
  • Классы, оставшиеся в PermGen после повторного развертывания приложения несколько раз (чаще в Dev, чем Prod)
  • Тяжелое использование классов прокси, которые создаются синтетически во время выполнения. Легко создавать новые классы прокси, когда одно определение класса можно повторно использовать для нескольких экземпляров.

Ответ 3

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

http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html

http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html

Ответ 4

Вы делаете что-то напуганное цепочкой загрузчиков классов? Вы звоните intern() в связке строк?

Ответ 7

Наиболее распространенными причинами, которые я видел, являются:

  • Загружаются классы Java
  • JAXBContext.newInstance
  • String.intern()