Что хранится в metaspace java
Java 8: от PermGen к MetaSpace
(Сокращённый перевод статьи Пьера-Хьюза Шарбонне)
Как уже сообщалось ранее на Java One, в Java 8 версии HotSpot планируется отказаться от PermGen пространства в пользу новой его вариации — Metaspace. Ранний доступ к JDK 8 даёт возможность наблюдать Metaspace в действии, чем и воспользовался автор оригинальной статьи чтоб узнать, какие преимущества даёт MetaSpace в сравнении с PermGen, и убедится во всём непосредственно.
Подробнорсти под катом.
Что такое Metaspace
В рамках мерджа HotSpot с JRockit хранение метаданных о классах будет осуществляться в нативной памяти, по аналогии с JRockit и IBM JVM. Часть нативной памяти, отведённая под эти метаданные, носит название Metaspace.
Итак, Metaspace это замена PermGen, основное отличие которой с точки зрения Java-программистов — возможность динамически расширятся, органиченная по умолчанию только размером нативной памяти. Параметры PermSize и MaxPermSize отныне упразднены (получив эти параметры JVM будет выдавать предупреждение о том, что они более не действуют), и вместо них вводится опциональный параметр MaxMetaspaceSize, посредством которого можно задать ограничение на размер Metaspace.
В результате максимальный Metaspace по умолчанию не ограничен ничем кроме предела объёма нативной памяти. Но его можно по желанию ограничить параметром MaxMetaspaceSize, аналогичным по сути к MaxPermSize.
Предполагается, что таким образом можно будет избежать ошибки «java.lang.OutOfMemoryError: PermGen space» за счёт большей гибкости динамического изменения размера Metaspace. Но, конечно, если размер Metaspace достигнет своей границы — будь то максимум объёма нативной памяти, или лимит заданный в MaxMetaspaceSize — будет выброшено аналогичное исключение: «java.lang.OutOfMemoryError: Metadata space».
Сборка мусора
Логи Garbage Collector-а будут сообщать также и о сборке мусора в Metaspace.
Сама сборка мусора, если верить автору статьи, будет происходить при достижении Metaspace размера, заданного в MaxMetaspaceSize. Но его же эксперименты (см. ниже) показывают, что когда MaxMetaspaceSize не задан, сборка мусора в Metaspace тоже осуществляется перед каждым его динамическим увеличением.
Эксперименты
В оригинальной статье автор также приводит графики использования памяти и логи Garbage Collector-а — для тех кому это интересно. Графики и логи должны быть понятны без перевода.
От себя добавлю, что такое нововведение может быть полезно для запуска java кода на клиентских машинах. Например ant/maven билд скриптов, которым ранее иногда приходилось поднимать MaxPermSize для успешного завершения билда. А также будет весьма полезно в тех (пусть и редких) случаях, когда используются десктопные Java приложения, оганичение PermGen для которых никогда не имело особого смысла.
Русские Блоги
Java 8 metaspace
Вечное поколение
Существует много типов JVM, таких как Oralce-Sun Hotspot, Oralce JRockit, IBM J9, Taobao JVM (Taobao хороший вид!) И так далее. Конечно, лидером боевых искусств является Hotspot, это не спор. Следует отметить, что пространство PermGen доступно только в Oracle-Sun Hotspot JRockit и J9 не имеют этой области.
Постоянное поколение содержит все данные в виртуальной машине, которые могут быть получены с помощью отражения, такие как объекты класса и метода. Разные виртуальные машины Java могут совместно использовать классы, поэтому постоянное поколение делится на область только для чтения и область чтения-записи.
Метаданные, используемые JVM для описания классов и методов, используемых в приложении, также сохраняются в постоянном поколении. Сколько места для генерации будет использовать JVM, зависит от того, сколько классов использует приложение. Кроме того, классы и методы в библиотеке Java SE также хранятся здесь.
Если JVM обнаружит, что некоторые классы больше не нужны, она восстановит (выгрузит) эти классы и освободит их пространство для использования другими классами. Полный GC восстановит длительное поколение.
Постоянный размер поколения
Почему удалить постоянное поколение
Так куда же делись метаданные для JVM?
Элемент пространства (Метапространство)
Пространство постоянного поколения полностью удалено, и оно заменено областью, названной metaspace. После удаления постоянного поколения очевидно, что JVM игнорирует два параметра PermSize и MaxPermSize, и вы больше не видите исключение java.lang.OutOfMemoryError: PermGen error.
HotSpot JVM в JDK 8 теперь использует локальную память для представления метаданных класса. Эта область называется метапространством.
Модель распределения памяти в метапространстве
Давайте посмотрим, как JVM выделяет пространство виртуальной памяти для метаданных
Понимать _mark и _klass указатели
Чтобы понять картинку ниже, вы должны выяснить, что это за указатели.
В JVM каждый объект имеет указатель на свой собственный класс, но этот указатель указывает только на определенный класс реализации, а не на интерфейс или абстрактный класс.
_mark: 4 байта константы
_klass: указывает на второе поле в макете памяти 4-байтового объекта указателя класса (_klass, в 32-битной JVM, смещение от позиции объекта в памяти равно 4, а 64-битное равно 8) Является ли определение класса объекта в памяти.
_mark: 8-байтовая константа
_klass: 8-байтовый указатель на класс
64-битная JVM с включенным сжатием указателей: _mark: 8-байтовая константа
_klass: 4-байтовый указатель на класс
Расположение памяти объектов Java
Сжатый указатель класса Space
Эта область существует только в том случае, если сжатие указателя класса включено на 64-разрядных платформах. Для 64-битных платформ для сжатия размера указателя _klass в объекте JVM вводится пространство указателя сжатого класса (пространство указателя сжатого класса).
Расположение памяти после сжатия указателей
Указатель на метаданные класса в объекте будет сжат до 32 бит
Пространство сжатия указателя класса будет иметь базовый адрес
Разница между мета-пространством и указателем как пространство сжатия
Пространство сжатия указателя класса содержит только метаданные класса, такие как InstanceKlass, ArrayKlass, которые вступают в силу только при включенной опции UseCompressedClassPointers. Для повышения производительности здесь также хранится таблица виртуальных методов в Java. Какие типы метаданных хранятся здесь?
Метапространство содержит другие относительно большие метаданные класса, такие как методы, байтовые коды и пулы констант.
Настройка метапространства
Тюнинг MaxMetaspaceSize
Настройка CompressedClassSpaceSize
Некоторые инструменты в метапространстве
Улучшить производительность GC
Если вы понимаете концепцию metaspace, легко обнаружить, что производительность GC была улучшена.
Метапространство в java8 суммируется следующим образом:
Состояние пермского пространства
Все это пространство памяти будет удалено.
Параметры JVM: PermSize и MaxPermSize игнорируются, и выдается предупреждение (если эти два параметра установлены при включении).
Модель распределения памяти в метапространстве
Большая часть метаданных класса размещается в локальной памяти.
«Классы», используемые для описания метаданных класса, были удалены.
Метапространственная емкость
По умолчанию метаданные класса ограничены только доступной локальной памятью (емкость зависит от объема виртуальной памяти, доступной для 32-разрядных или 64-разрядных операционных систем).
Новый параметр (MaxMetaspaceSize) используется для ограничения размера локальной памяти, выделяемой метаданным класса. Если этот параметр не указан, метаскоп будет динамически корректироваться по мере необходимости во время выполнения.
Metaspace сборка мусора
Сборка мусора для классов зомби и загрузчиков классов будет выполняться, когда использование метаданных достигнет значения, установленного параметром «MaxMetaspaceSize».
Необходимо своевременно отслеживать и корректировать метапространство, чтобы снизить частоту сбора мусора и уменьшить задержку. Непрерывная сборка мусора в метапространстве указывает на возможную утечку памяти, вызванную классами, загрузчиками классов или неправильными настройками размера.
Влияние кучи памяти Java
Некоторые разные данные были перемещены в пространство кучи Java. После обновления до JDK8 вы увидите, что пространство кучи Java увеличилось.
Метапространственный мониторинг
Использование метапространства может быть получено из подробного журнала GC HotSpot 1.8.
Два инструмента, Jstat и JVisualVM, были обновлены при тестировании с версией b75, но вы все еще можете увидеть внешний вид старого пространства PermGen.
Сравнение PermGen и Metaspace во время выполнения
Чтобы лучше понять поведение во время выполнения пространства памяти Metaspace,
Будут протестированы следующие сценарии:
Используйте JDK1.7 для запуска программ на Java, отслеживания и исчерпания объема памяти PermGen по умолчанию, равного 85 МБ.
Используйте JDK1.8 для запуска программ на Java и отслеживания процесса динамического роста и сбора мусора в новом пространстве памяти Metaspace.
Используйте JDK1.8 для запуска Java-программы и имитации исчерпания пространства памяти Metaspace объемом 128 МБ, установленного параметром «MaxMetaspaceSize».
Сначала создан код, который имитирует PermGen OOM
Выше приведен простой ClassA, скомпилируйте его в байт-код класса и поместите его в D: / classes, используйте URLClassLoader для загрузки этого типа в тестовый код Вышеупомянутый класс скомпилирован в класс
Это можно увидеть на скриншоте JVisualVM выше: после загрузки более 60 000 классов PermGen исчерпан. Мы также можем наблюдать процесс истощения через вывод программы и GC.
Вывод программы (извлеченная часть)
JDK 1.8 @ 64-битный тест на динамическое изменение размера Metaspace
Java Metaspace space: не ограничено (по умолчанию)
Как вы можете видеть на скриншоте выше, JVM Metaspace динамически расширяется, а использование локальной памяти увеличено с 20 МБ до 646 МБ, чтобы удовлетворить растущий спрос на память данных классов в программе. Мы также можем наблюдать событие сборки мусора JVM, пытающимся уничтожить мертвый класс или объект загрузчика классов. Однако из-за утечки нашей программы у JVM нет другого выбора, кроме как динамически расширять пространство памяти Metaspace. Программа загружает более 100 000 классов без событий OOM.
Пространство метапространства Java: 128 МБ (-XX: MaxMetaspaceSize = 128 м)
Это можно увидеть на скриншоте JVisualVM выше: после загрузки более 20 000 классов Metaspace исчерпан, очень похоже на среду выполнения JDK1.7. Мы также можем наблюдать процесс истощения через вывод программы и GC. Еще одним интересным явлением является то, что зарезервированное использование собственной памяти более чем в два раза превышает установленный максимальный размер. Это может указывать на то, что, если возможно, вы можете точно настроить стратегию емкости метапространства, чтобы не тратить локальную память.
Следующее исключение видно из вывода программы Java.
Избавляемся от мусора в Java
Что такое сборка мусора, зачем она нужна и как работает
Для работы любого приложения требуется память. Однако память компьютера ограничена. Поэтому важно ее очищать от старых неиспользуемых данных, чтобы освободить место для новых.
Кто занимается этой очисткой? Как и когда очищается память? Как выглядит структура памяти? Давайте разберем с этим подробнее.
Структура памяти Java
Память в Java состоит из следующих областей:
Структура памяти Java
Native Memory — вся доступная системная память.
Stack (стек) — используется для хранения локальных переменных и стека вызовов метода. Для каждого потока выделяется свой стек.
Metaspace (метаданные) — в этой памяти хранятся метаданные классов и статические переменные. Это пространство также является общими для всех. Так как metaspace является частью native memory, то его размер зависит от платформы. Верхний предел объема памяти, используемой для metaspace, можно настроить с помощью флага MaxMetaspaceSize.
PermGen (Permanent Generation, постоянное поколение) присутствовало до Java 7. Начиная с Java 8 ему на смену пришла область Metaspace.
CodeCache (кэш кода) — JIT-компилятор компилирует часто исполняемый код, преобразует его в нативный машинный код и кеширует для более быстрого выполнения. Это тоже часть native memory.
Сборка мусора: введение
Что такое «мусор»? Мусором считается объект, который больше не может быть достигнут по ссылке из какого-либо объекта. Поскольку такие объекты больше не используются в приложении, то их можно удалить из памяти.
Например, на диаграмме ниже объект fruit2 может быть удален из памяти, поскольку на него нет ссылок.
Мусор
Что такое сборка мусора? Сборка мусора — это процесс автоматического управления памятью. Освобождение памяти (путем очистки мусора) выполняется автоматически специальным компонентом JVM — сборщиком мусора (Garbage Collector, GC). Нам, как программистам, нет необходимости вмешиваться в процесс сборки мусора.
Источник: Oracle.com
Сборка мусора: процесс
Для сборки мусора используется алгоритм пометок (Mark & Sweep). Этот алгоритм состоит из трех этапов:
Sweep (очистка). На этом шаге освобождается память, занятая объектами, не отмеченными на предыдущем шаге.
Compact (уплотнение). Объекты, пережившие очистку, перемещаются в единый непрерывный блок памяти. Это уменьшает фрагментацию кучи и позволяет проще и быстрее размещать новые объекты.
Mark & Sweep GC
Поколения объектов
Что такое поколения объектов?
Для оптимизации сборки мусора память кучи дополнительно разделена на четыре области. В эти области объекты помещаются в зависимости от их возраста (как долго они используются в приложении).
Young Generation (молодое поколение). Здесь создаются новые объекты. Область young generation разделена на три части раздела: Eden (Эдем), S0 и S1 (Survivor Space — область для выживших).
Old Generation (старое поколение). Здесь хранятся давно живущие объекты.
Поколения в куче
Что такое Stop the World?
Когда запускается этап mark, работа приложения останавливается. После завершения mark приложение возобновляет свою работу. Любая сборка мусора — это «Stop the World».
Что такое гипотеза о поколениях?
Как уже упоминалось ранее, для оптимизации этапов mark и sweep используются поколения. Гипотеза о поколениях говорит о следующем:
Большинство объектов живут недолго.
Если объект выживает, то он, скорее всего, будет жить вечно.
Этапы mark и sweep занимают меньше времени при большом количестве мусора. То есть маркировка будет происходить быстрее, если анализируемая область небольшая и в ней много мертвых объектов.
Таким образом, алгоритм сборки мусора, использующий поколения, выглядит следующим образом:
Сборка мусора поколениями
Новые объекты создаются в области Eden. Области Survivor (S0, S1) на данный момент пустые.
Когда область Eden заполняется, происходит минорная сборка мусора (Minor GC). Minor GC — это процесс, при котором операции mark и sweep выполняются для young generation (молодого поколения).
После Minor GC живые объекты перемещаются в одну из областей Survivor (например, S0). Мертвые объекты полностью удаляются.
По мере работы приложения пространство Eden заполняется новыми объектами. При очередном Minor GC области young generation и S0 очищаются. На этот раз выжившие объекты перемещаются в область S1, и их возраст увеличивается (отметка о том, что они пережили сборку мусора).
При следующем Minor GC процесс повторяется. Однако на этот раз области Survivor меняются местами. Живые объекты перемещаются в S0 и у них увеличивается возраст. Области Eden и S1 очищаются.
Объекты между областями Survivor копируются определенное количество раз (пока не переживут определенное количество Minor GC) или пока там достаточно места. Затем эти объекты копируются в область Old.
Major GC. При Major GC этапы mark и sweep выполняются для Old Generation. Major GC работает медленнее по сравнению с Minor GC, поскольку старое поколение в основном состоит из живых объектов.
Преимущества использования поколений
Minor GC происходит в меньшей части кучи (
2/3 от кучи). Этап маркировки эффективен, потому что область небольшая и состоит в основном из мертвых объектов.
Недостатки использования поколений
В каждый момент времени одно из пространств Survivor (S0 или S1) пустое и не используется.
Сборка мусора: флаги
В этом разделе приведены некоторые важные флаги, которые можно использовать для настройки процесса сборки мусора.
Флаг
Описание
Первоначальный размер кучи
Максимальный размер куча
Отношение размера Old Generation к Young Generation
Отношение размера Eden к Survivor
Возраст объекта, когда объект перемещается из области Survivor в область Old Generation
Типы сборщиков мусора
Сборщик мусора
Описание
Преимущества
Когда использовать
Флаги для включения
Использует один поток.
Эффективный, т.к. нет накладных расходов на взаимодействие потоков.
Работа с небольшими наборами данных.
Использует несколько потоков.
Многопоточность ускоряет сборку мусора.
В приоритете пиковая производительность.
Допустимы паузы при GC в одну секунду и более.
Работа со средними и большими наборами данных.
Для приложений, работающих на многопроцессорном или многопоточном оборудовании.
Выполняет некоторую тяжелую работу параллельно с работой приложения.
Может использоваться как на небольших системах, так и на больших с большим количеством процессоров и большим количеством памяти.
Когда время отклика важнее пропускной способности.
Паузы GC должны быть меньше одной секунды.
Выполняет всю тяжелую работу параллельно с работой приложения.
В приоритете время отклика.
Сборщики мусора в Java
Инструменты мониторинга GC
Что мониторить?
Частота запуска сборки мусора. Так как GC вызывает «stop the world», поэтому чем время сборки мусора меньше, тем лучше.
Длительность одного цикла сборки мусора.
Как мониторить сборщик мусора?
Для мониторинга можно использовать следующие инструменты:
Для включения логирования событий сборщика мусора добавьте следующие параметры JVM:
Русские Блоги
Metaspace One: общее введение в Metaspace (причина замены постоянной генерации, характеристики метапространства, метод анализа памяти метапространства)
Справочник статей
Исходная ссылка: https://www.cnblogs.com/duanxz/p/3520829.html Добавить верстку уценки.
обзор
Сборщик мусора в основном восстанавливает неиспользуемую область памяти в области кучи и организует соответствующую область. Область кучи делится на «молодое поколение» и «старое поколение» в зависимости от времени выживания памяти объекта или размера объекта. Объекты в «молодом поколении» нестабильны и их легко производить, а объекты в «старом поколении» относительно стабильны и их трудно генерировать. Причиной их разделения является разделение и завоевание. В соответствии с характеристиками блоков памяти в разных регионах применяются разные алгоритмы восстановления памяти для повышения эффективности сбора мусора в области кучи.
1. Metaspace заменяет постоянное поколение
1.1, прочное поколение
Постоянное поколение содержит все данные, которые могут быть получены путем отражения в виртуальной машине, такие как объекты Class и Method. Разные виртуальные машины Java могут совместно использовать классы, поэтому постоянное поколение делится на область только для чтения и область чтения-записи.
Метаданные, используемые JVM для описания классов и методов, используемых в приложении, также сохраняются в постоянном поколении. Количество постоянного пространства генерации, используемого при запуске JVM, зависит от того, сколько классов используется приложением. Кроме того, классы и методы в библиотеке Java SE также хранятся здесь.
Если JVM обнаружит, что некоторые классы больше не нужны, она освободит (разгрузит) эти классы и освободит их пространство для использования другими классами. Full GC будет осуществлять сбор постоянного поколения.
Постоянный размер поколения
1.2 Зачем удалять постоянное поколение
1.3 Состояние пространства PermGen после удаления постоянного поколения
Эта часть пространства памяти будет полностью удалена.
Параметры JVM: PermSize и MaxPermSize будут игнорироваться, и будет выдано предупреждение (если эти два параметра установлены при включении).
2. Метапространство
С появлением JDK8 PermGen больше не доступен для JVM. Но метаданные класса все еще там, но они больше не хранятся в смежном пространстве кучи, а перемещаются в собственную память, называемую «Метапространство».
2.1 Состав метапространства
Klass Metaspace и NoKlass Mestaspace совместно используются всеми загрузчиками классов, поэтому загрузчики классов должны распределять память, но каждый загрузчик классов имеет SpaceManager для управления небольшими блоками памяти, которые принадлежат этому классу. Если Klass Metaspace израсходован, это будет OOM, но при нормальных обстоятельствах это не так. NoKlass Mestaspace медленно объединяется с блоками памяти. Когда предел не достигнут, цепочка будет непрерывно удлиняться, чтобы позволить ему Можете продолжать работать.
Природа метапространства аналогична природе постоянного поколения, которая является реализацией области метода в спецификации JVM. Однако самое большое различие между метапространством и постоянным генерированием заключается в том, что метапространство не находится на виртуальной машине, а использует локальную память. Следовательно, по умолчанию размер метапространства ограничен только локальной памятью, но размер метапространства может быть задан следующими параметрами:
2.2 Особенности Metaspace
2.3 Модель выделения памяти метапространства
Давайте посмотрим, как JVM выделяет виртуальную память для метаданных.
Понимать _mark и _klass указатели
Чтобы понять картинку ниже, вы должны выяснить, что это за указатели.
В JVM каждый объект имеет указатель на свой собственный класс, но этот указатель указывает только на определенный класс реализации, а не на интерфейс или абстрактный класс.
_mark: 4-байтовая константа
_klass: второе поле в макете памяти 4-байтового объекта-указателя, которое указывает на класс (_klass, в 32-разрядной JVM смещение относительно расположения объекта в памяти равно 4, 64-битный это 8) указывает на определение класса объекта в памяти.
64-битная JVM:
_mark: 8-байтовая константа
_klass: 8-байтовый указатель на класс
64-битная JVM с включенным сжатием указателей: _mark: 8-байтовая константа
_klass: 4-байтовый указатель на класс
Структура памяти объектов Java
Сжатый указатель класса Space
Эта область будет существовать только в том случае, если сжатие указателя класса включено на 64-разрядных платформах. Для 64-битных платформ для сжатия размера указателя _klass в объекте JVM вводится пространство указателя сжатого класса.
Расположение памяти после сжатых указателей
Сводка сжатия указателя
Разница между метапространством и пространством сжатия указателя класса
3. Управление памятью Metaspace
Управление памятью метапространства завершается виртуальной машиной метапространства. Раньше нам требовались разные сборщики мусора для обработки метаданных класса, а сейчас нам нужно только выполнить код C ++ виртуальной машины метас пространства. В метапространстве жизненный цикл класса и его метаданных такой же, как у соответствующего загрузчика классов. Другими словами, до тех пор, пока загрузчик классов выживает, метаданные загруженного класса также являются живыми, поэтому они не будут повторно использованы.
На рисунке выше показано, как распределить блоки кортежей в области отображения виртуальной памяти. Загрузчики классов 1 и 3 указывают, что используются отражающие или анонимные загрузчики классов, и они используют куски определенного размера. Загрузчики классов 2 и 4 используют небольшие или средние куски в зависимости от количества внутренних записей.
В-четвертых, настройка Metaspace
Тюнинг MaxMetaspaceSize
Настройка CompressedClassSpaceSize
После каждой сборки мусора Metaspace VM автоматически корректирует верхний водяной знак, чтобы отложить следующую сборку мусора в Metaspace.
В-пятых, инструменты, которые Metaspace может использовать
Для Metaspace некоторые инструменты, поставляемые с JDK, были изменены для отображения информации Metaspace:
Пример 3: jcmd 5943 GC.class_stats
В-шестых, улучшить производительность GC
Если вы понимаете концепцию metaspace, легко обнаружить, что производительность GC была улучшена.
Метапространство в java8 суммируется следующим образом:
Семь, проблема метапространства
Как упоминалось ранее, виртуальная машина метапространства принимает форму выделения блоков, а размер блока определяется типом загрузчика классов. Информация о классе не является фиксированным размером, поэтому возможно, что размер выделенного свободного блока и блока, требуемого классом, различны. В этом случае может возникнуть фрагментация. Виртуальные машины Metaspace в настоящее время не поддерживают операции сжатия, поэтому фрагментация в настоящее время является самой большой проблемой.