Статьи

Java 8: от PermGen к Metaspace

Как вы, возможно, знаете, JDK 8 Early Access теперь доступен для скачивания. Это позволяет разработчикам Java экспериментировать с некоторыми новыми языковыми и исполняющими функциями Java 8. Одной из этих функций является полное удаление пространства Permanent Generation (PermGen), которое было объявлено Oracle с момента выпуска JDK 7. Interned strings например, уже были удалены из пространства PermGen начиная с JDK 7. Релиз JDK 8 завершает вывод из эксплуатации. Эта статья поделится информацией, которую мы до сих пор нашли о преемнике PermGen : Metaspace . Мы также сравним поведение во время выполнения HotSpot 1.7 против HotSpot 1.8 (b75) при выполнении объектов метаданных класса «утечка» из программы Java. Окончательные спецификации, флаги настройки и документация по Metaspace должны быть доступны после официального выпуска Java 8.

Метапространство:

Новое пространство памяти рождается

JVK HotSpot JDK 8 теперь использует собственную память для представления метаданных класса и называется Metaspace; похож на Oracle JRockit и IBM JVM . Хорошая новость заключается в том, что это означает, что больше нет java.lang.OutOfMemoryError: проблемы с пространством PermGen и вам больше не нужно настраивать и контролировать это пространство памяти … не так быстро. Хотя это изменение невидимо по умолчанию, далее мы покажем вам, что вам все равно придется беспокоиться об объеме памяти метаданных класса. Также имейте в виду, что эта новая функция не устраняет утечки памяти классов и загрузчиков классов. Вам нужно будет отследить эти проблемы, используя другой подход и изучив новое соглашение об именах. Я рекомендую прочитать сводку удаления PermGen и комментарии Джона на эту тему.

В итоге:

Космическая обстановка

  • Это пространство памяти полностью удалено.
  • Аргументы JVM PermSize и MaxPermSize игнорируются и выдается предупреждение, если оно присутствует при запуске.

Модель распределения памяти в метапространстве

  • Большинство выделений для метаданных класса теперь выделяются из собственной памяти.
  • Классы, которые использовались для описания метаданных класса, были удалены.

Метапространственная емкость

  • По умолчанию выделение метаданных класса ограничено объемом доступной собственной памяти (емкость, конечно, будет зависеть от того, используете ли вы 32-разрядную JVM против 64-разрядной вместе с доступностью виртуальной памяти ОС).
  • Доступен новый флаг (MaxMetaspaceSize), позволяющий ограничить объем собственной памяти, используемой для метаданных класса. Если вы не укажете этот флаг, Metaspace будет динамически изменять размер в зависимости от требований приложения во время выполнения.

Metaspace сборка мусора

  • Сборка мусора мертвых классов и загрузчиков классов запускается, когда использование метаданных класса достигает «MaxMetaspaceSize».
  • Очевидно, что для ограничения частоты или задержки таких сборок мусора потребуется надлежащий мониторинг и настройка Metaspace. Чрезмерный сбор мусора в Metaspace может быть признаком классов, утечки памяти в загрузчиках классов или недостаточного размера для вашего приложения.

Влияние пространства кучи Java

  • Некоторые разные данные были перемещены в пространство кучи Java. Это означает, что вы можете наблюдать увеличение пространства кучи Java после будущего обновления JDK 8.

Метапространственный мониторинг

  • Использование Metaspace доступно из подробного вывода журнала HotSpot 1.8 GC.
  • Jstat & JVisualVM не были обновлены на данный момент, основываясь на нашем тестировании с b75, и старые ссылки на пространство PermGen все еще присутствуют.

Теперь достаточно теории, давайте посмотрим на это новое пространство памяти в действии через нашу утечку Java-программы…

Сравнение PermGen и Metaspace во время выполнения

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

Будут протестированы следующие сценарии:

  • Запустите программу Java, используя JDK 1.7, чтобы отслеживать и истощать объем памяти PermGen, установленный на 128 МБ.
  • Запустите программу Java, используя JDK 1.8 (b75), чтобы отслеживать динамическое увеличение и сбор мусора в новом пространстве памяти Metaspace.
  • Запустите программу Java, используя JDK 1.8 (b75), чтобы смоделировать истощение Metaspace, установив значение MaxMetaspaceSize в 128 МБ.

JDK 1.7 @ 64-bit — истощение PermGen

  • Java-программа с 50K настроенными итерациями
  • Пространство кучи Java 1024 МБ
  • Пространство Java PermGen 128 МБ (-XX: MaxPermSize = 128 м)

Как видно из формы JVisualVM, истощение PermGen было достигнуто после загрузки около 30K + классов. Мы также можем увидеть это истощение из программы и вывода GC.

1
2
3
4
5
6
7
Class metadata leak simulator
 
Author: Pierre-Hugues Charbonneau
 
http://javaeesupportpatterns.blogspot.com
 
ERROR: java.lang.OutOfMemoryError: PermGen space

Теперь давайте запустим программу, используя HotSpot JDK 1.8 JRE.

JDK 1.8 @ 64-bit — динамическое изменение размера Metaspace

  • Java-программа с 50K настроенными итерациями
  • Пространство кучи Java 1024 МБ
  • Пространство метапространства Java: неограниченное (по умолчанию)

Как вы можете видеть из подробного вывода GC, JVM Metaspace динамически расширялась с 20 МБ до 328 МБ зарезервированной собственной памяти, чтобы удовлетворить возросший объем памяти метаданных класса из нашей программы на Java. Мы также могли наблюдать события сбора мусора при попытке JVM уничтожить любой мертвый класс или объект загрузчика классов. Поскольку наша Java-программа протекает, у JVM не было выбора, кроме как динамически расширять пространство памяти Metaspace. Программа была в состоянии выполнить свои 50K итераций без события OOM и загрузила 50K + Классы. Давайте перейдем к нашему последнему сценарию тестирования.

JDK 1.8 @ 64-bit — истощение метапространства

  • Java-программа с 50K настроенными итерациями
  • Пространство кучи Java 1024 МБ
  • Пространство метапространства Java: 128 МБ (-XX: MaxMetaspaceSize = 128 м)

Как видно из формы JVisualVM, истощение Metaspace было достигнуто после загрузки около 30K + классов; очень похоже на пробег с JDK 1.7. Мы также можем видеть это из программы и вывода GC. Еще одно интересное наблюдение заключается в том, что зарезервированная собственная область памяти была в два раза больше максимального указанного размера. Это может указывать на некоторые возможности точной настройки политики изменения размера Metaspace, если это возможно, во избежание потери памяти.

Теперь найдите ниже Исключение, которое мы получили из вывода программы Java.

1
2
3
4
5
6
7
Class metadata leak simulator
 
Author: Pierre-Hugues Charbonneau
 
http://javaeesupportpatterns.blogspot.com
 
ERROR: java.lang.OutOfMemoryError: Metadata space

Готово!

Как и ожидалось, ограничение Metaspace до 128 МБ, как мы делали для базового запуска с JDK 1.7, не позволило нам завершить итерации нашей программы по 50 КБ. Новая ошибка OOM была выдана JVM. Вышеупомянутое событие OOM было вызвано JVM из Metaspace после сбоя выделения памяти.

# metaspace.cpp

Заключительные слова

Я надеюсь, что вы оценили этот ранний анализ и эксперимент с новым Java 8 Metaspace. Текущие наблюдения определенно указывают на то, что для того, чтобы избежать таких проблем, как чрезмерное GC в Metaspace или условия OOM, вызванные последним сценарием тестирования, потребуется надлежащий мониторинг и настройка Будущие статьи могут включать сравнения производительности, чтобы определить потенциальные улучшения производительности, связанные с этой новой функцией.

Ссылка: Java 8: от PermGen до Metaspace от нашего партнера по JCG Пьера-Хьюга Шарбонно из блога поддержки шаблонов Java EE и учебного курса по Java .