в моей последней статьеНе переворачивайте, эта статья определенно даст вам глубокое понимание загрузки классов Java и анализа исходного кода ClassLoader [JVM, часть 2]Я полагаю, что все имеют относительно полное представление о механизме загрузки классов Java После того, как класс загружен, как данные байт-кода сохраняются в памяти виртуальной машины Java? Как виртуальная машина Java выделяет память для экземпляров класса или переменных-членов? Да, эти два вопроса предполагают знание структуры памяти JVM, тогда эта статья ответит.
@[toc]
1. Структура памяти или область данных времени выполнения?
Чтобы ответить на эти вопросы в этой статье, нам сначала нужно понять структуру памяти виртуальной машины Java.
С определенной точки зрения,Структура памяти виртуальной машины Java == область данных времени выполнения, в «Спецификации виртуальной машины Java» используется термин «область данных времени выполнения», и нет такого понятия, как структура памяти. Просто структура памяти звучит более уместно и живо,Поэтому полезно знать, что структура памяти — это смысл области данных времени выполнения.! Не нужно заморачиваться с этой проблемой~
2. Область рабочих данных
JVM разделена на три основные подсистемы: подсистема загрузчика классов, область данных времени выполнения и механизм выполнения. И сегодняшняя статья в основном объясняет область данных времени выполнения (Области данных времени выполнения)
Кстати, пул констант среды выполнения также войдет в область методов, что означает, что пул констант уже включен в область методов.
Обратите особое внимание на области кучи и методов Java.обмен потокамииз. другиеприватный потокиз.
3. Совместное использование потоков: куча Java, область методов
Давайте сначала взглянем на кучу Java и область методов, разделяемую потоками!
3.1, куча Java
Куча Java используется всеми потоками и создается при запуске виртуальной машины.
Куча Java — это самая большая область, занимаемая пространством памяти.Куча Java используется для храненияэкземпляр объектаимножество, то есть здесь хранятся новые объекты в нашем коде через новое ключевое слово. Так что это стало основным лагерем деятельности сборщика мусора, поэтому у него есть псевдонимкуча сборщика мусора, и один процесс JVM имеет одну и только одну кучу Java. Согласно правилам сборщика мусора, мы можем дополнительно разделить кучу Java.Конкретная структура памяти кучи Java показана на следующем рисунке:
Куча Java = старое поколение + молодое поколение
Молодое поколение = Эдем + S0 + S1
Эдем по умолчанию: от: до = 8: 1: 1
Если вы внимательно посмотрите на приведенную выше диаграмму структуры кучи Java, вы можете найти слова -Xms и -Xmn. Да, это параметр JVM, который управляет кучей. Фактически, мы можем динамически управлять различными пространствами в Java. куча через параметры JVM. Параметров о размере JVM много, но есть только несколько часто используемых. Их не так много, и их будет легко запомнить, если вы будете их больше использовать. Поговорим об общих параметры JVM о куче:
-Xms
: начальный размер емкости кучи (куча включает молодое поколение и старое поколение). Например: -Xms 20M-Xmx
: общий (максимальный) размер кучи. Например: -Xmx 30MПримечание. Рекомендуется установить для -Xms и -Xmx одно и то же значение, чтобы избежать перераспределения памяти JVM после каждой сборки мусора!-Xmn
: Вместимость нового поколения. Например: -Xmn 10M-XX: SurvivorRatio
Установите соотношение параметров Eden, form и to [Соотношение параметров Eden, form и to по умолчанию равно 8:1:1] Например: -XX: SurvivorRatio=8 представляет соотношение 8:1:1
Хотя параметры старого поколения не задаются напрямую, два параметра, размер пространства кучи и размер пространства молодого поколения, могут быть установлены для косвенного управления:Размер пространства старого поколения = Размер пространства кучи - Большой размер пространства молодого поколения
Когда в нашей куче Java достаточно места для завершения выделения экземпляра, а куча не может расширяться, наш общийOutOfMemoryErrorИсключение, это то, что мы часто говоримOOMаномальный
3.2 Могут ли другие потоки продолжать работать после переполнения кучи памяти JVM?
После переполнения кучи памяти JVM это также исключение OOM.В Интернете есть очень популярный вопрос на собеседованиях: После переполнения памяти кучи JVM могут ли продолжать работать другие потоки?
На самом деле эта проблема требует специального сценарного анализа. Но в целом поток, который возникает OOM, будет завершен (если только код не написан слишком плохо), куча, занятая удерживаемым потоком объектом, будет занята gc, а память будет освобождена. Поскольку gc выполняется до того, как произойдет OOM, даже если другие потоки могут работать нормально, это будет иметь большее влияние из-за частого gc.
То есть поток, в котором происходит OOM, обычно умирает, то есть он будет завершен. Поскольку gc выполняется до того, как произойдет OOM, даже если другие потоки могут работать нормально, это будет иметь большее влияние из-за частого gc.
3.3 Область метода
Возьмем в качестве примера виртуальную машину HotSpot вJDK1.7, область метода называетсяпостоянное поколение, отJDK1.8Начинать,МетапространствоЭто то, что мы называем областью метода!
То есть, если друзья вокруг вас все еще говорят о постоянной генерации, то вы говорите о концепции до 1.8.После 1.8 от концепции постоянной генерации отказались!
Область методов, как и упомянутая выше куча Java, совместно используется всеми потоками и используется для хранения таких данных, как информация о классе, константы, статические переменные и код, скомпилированный компилятором реального времени, который был загружен виртуальной машиной. . Хотя спецификация виртуальной машины Java описывает область методов как логическую часть кучи, у нее есть псевдоним Non-Heap (не-куча), который следует отличать от кучи Java.
Спецификация виртуальной машины Java определяет область метода следующим образом: Он хранит структурную информацию каждого класса, такую как пул констант времени выполнения, поля, данные методов, содержимое байт-кода конструкторов и обычных методов, а также включает некоторые специальные методы, используемые при инициализации классов, экземпляров и интерфейсов.
3.4 Область метода до JDK1.8
Что касается виртуальной машины HotSpot, то до JDK1.8 область методов также называлась постоянным поколением, и эта область методов будетjava.lang.OutOfMemoryError: PermGen spaceисключение, обратите внимание, чтопостоянное поколениеИнформация об исключении, мы также можем контролировать размер области метода с помощью начальных параметров:
-XX:PermSize Установить минимальное пространство области метода -XX:MaxPermSize Установить максимальное пространство области метода
В виртуальной машине HotSpot до JDK7 строки, включенные в пул строковых констант, хранились в постоянном поколении, что вызывало ряд проблем с производительностью и ошибки нехватки памяти. Особенно ярким примером являетсяString
изстажер()метод
3.5 Область методов после JDK1.8
Заявление о том, что после JDK8 не существует постоянного поколения, стало называтьсяметапространство, и обнажает старость из метапространства. Метапространство помещается в локальную память, поэтому максимальное пространство метапространства — это пространство памяти системы, поэтому больше не будет ошибок переполнения памяти, таких как постоянное поколение, и не будет такой вещи, как перемещение слил данные в область подкачки. . Пользователь может установить максимальное доступное пространство для метапространства, и по умолчанию емкость метапространства динамически увеличивается в соответствии с размером метаданных класса. Для 64-битной JVM на стороне сервера по умолчанию–XX:MetaspaceSize
Значение составляет 21 МБ. то естьРазмер метапространства по умолчанию составляет 21 МБ..
== Пока жив загрузчик классов, метаданные загруженного класса тоже живы и не будут переработаны! То есть жить и умереть вместе ==
3.6 Почему область методов так сильно изменилась после JDK1.8?
Это изменение может быть в основном основано на следующих двух причинах:
1. Поскольку память постоянного поколения (PermGen) часто переполняется, вызывая раздражениеjava.lang.OutOfMemoryError: PermGen
, поэтому разработчики JVM надеются, что этим участком памяти можно будет управлять более гибко, и такие ошибки OOM будут возникать не часто.
2. Удаление постоянного поколения (PermGen) может способствовать интеграции HotSpot JVM и JRockit VM, поскольку JRockit не имеет постоянного поколения.
Следует также отметить, что удаление постоянного поколения не означает, что проблема утечки пользовательского загрузчика классов решена. Следовательно, вы также должны следить за своим потреблением памяти, потому что в случае утечки она займет много вашей локальной памяти, а также может привести к тому, что область подкачки будет подкачиваться еще хуже.
4. Частный поток: счетчик программ, стек виртуальной машины Java, стек собственных методов.
Куча Java и данные в области метода являются общими, но некоторые части являются частными для потока. Частную часть потока можно разделить на три части: счетчик программ, стек виртуальной машины Java и стек собственных методов.
4.1 Стеки JVM
1. Каждый поток виртуальной машины Java имеет свой собственный стек виртуальной машины Java. Этот стек виртуальной машины Java создается одновременно с потоком, поэтому он имеет тот же жизненный цикл, что и поток.
2. Стек виртуальной машины Java описывает модель памяти выполнения ==метода Java==: каждый метод создает кадр стека одновременно с его выполнением, который используется для хранения таблицы локальных переменных, стека операндов, динамического ссылка, выход из метода и т. д. Информация, == Процесс каждого метода от вызова до завершения выполнения соответствует процессу укладки кадра стека в стек виртуальной машины Java до извлечения ==.
3.таблица локальных переменныхХранит различные примитивные типы данных, ссылки на объекты и типы returnAddress, известные во время компиляции.
1. Основные типы: восемь основных типов 2. Ссылка на объект: тип ссылки, который не эквивалентен самому объекту.В зависимости от различных реализаций виртуальных машин, это может быть указатель на начальный адрес объекта, или он может указывать на дескриптор, представляющий объект или другой объект. связанные объекты. 3. Тип returnAddress: указывает на адрес инструкции байт-кода.
64-битные типы данных long и double занимают 2 пространства локальных переменных (слотов), а остальные типы данных занимают только 1. Объем памяти, требуемый таблицей локальных переменных, выделяется во время компиляции.При входе в метод полностью определяется, сколько места локальной переменной этот метод должен выделить во фрейме, и размер таблицы локальных переменных не будет изменяться во время выполнения. выполнение метода.
4. Стек виртуальной машины Java может быть реализован с фиксированным размером, а также может динамически расширяться и сокращаться в соответствии с расчетами.Если используется фиксированный размер, емкость стека виртуальной машины Java для каждого потока может быть выбрана независимо, когда поток создан. В стеке виртуальной машины Java возникают два исключения, указанные в спецификации виртуальной машины:
- Если размер стека, запрошенный потоком, превышает максимальный размер, разрешенный стеком виртуальной машины Java, виртуальная машина Java выдаст
StackOverflowError
Исключение; то есть ошибка переполнения стека!рекурсия методадоходность коллаStackOverflowError
необычный результат. - Если стек виртуальной машины Java может быть динамически расширен, и он не может выделить достаточно памяти при попытке расширения или недостаточно памяти для создания соответствующего стека виртуальной машины Java при создании нового потока, виртуальная машина выдаст ошибку
OutOfMemoryError
аномальный. Это ошибка переполнения памяти OOM! (Запущено слишком много потоков)
Конечно, вы можете передать параметр-Xss
Настройте размер стека JVM!
4.2 Стеки нативных методов
== похож на виртуальный стек, за исключением того, что он обслуживает метод Native ==,приватный поток. Стек собственных методов также используется, когда виртуальная машина Java реализует интерпретатор набора инструкций на другом языке, таком как C. Если виртуальная машина Java не поддерживает метод natvie и не полагается на сам традиционный стек, ей не нужно поддерживать собственный стек методов.
Как и в стеке виртуальной машины Java, область стека собственных методов также создаетStackOverflowError
иOutOfMemoryError
аномальный.
Виртуальная машина HotSpot напрямую объединяет стек собственных методов и стек виртуальной машины в один.
4.3, счетчик программ
Индикатор номера строки байт-кода, выполняемого текущим потоком, используемый для записи адреса исполняемой байтовой инструкции виртуальной машины, частной для потока.
Важно отметить, что программный счетчик — единственный, который не указан в спецификации виртуальной машины Java каким-либо образом.
OutOfMemoryError
область ситуации.
5. Резюме структуры памяти JVM
1. Индикатор номера строки байт-кода, выполняемого текущим потоком, используется для записи адреса исполняемой байтовой инструкции виртуальной машины, которая является частной для потока. 2. Счетчик программ — единственный, который не указан в спецификации виртуальной машины Java каким-либо образом.
OutOfMemoryError
область ситуации.
Виртуальный стек Java:
1. Храните основные типы данных, ссылки на объекты, выходы методов и т. д. в приватном потоке. 2. Если емкость стека превышает максимальную емкость стека виртуальной машины Java,
StackOverflowError
Исключение; то есть ошибка переполнения стека!рекурсия методапроизводить 3. Если стек виртуальной машины Java может быть динамически расширен, для него не может быть применено достаточно памяти или недостаточно памяти для создания соответствующего стека виртуальной машины Java при создании нового потока, он выдастOutOfMemoryError
аномальный. Это ошибка переполнения памяти OOM! (Запущено слишком много потоков) 4. Параметры-Xss
Отрегулируйте размер стека JVM
Стек собственных методов:
1. Аналогичен виртуальному стеку, за исключением того, что он обслуживает метод Native и является закрытым для потока. 2,Виртуальная машина HotSpot напрямую объединяет стек собственных методов и стек виртуальной машины в один.
Куча Java:
Самая большая часть памяти java, все экземпляры объектов и массивы хранятся в куче java, где перерабатывается сборщик мусора и совместно используются потоки.
Куча Java = старое поколение + молодое поколение
Молодое поколение = Эдем + S0 + S1
Эдем по умолчанию: от: до = 8: 1: 1
Область метода:
1. Хранить загруженную информацию о классе, константы, статические переменные, данные кода, скомпилированные компилятором реального времени и т. д. Целью переработки является, в основном, повторная обработка пула констант и выгрузка типов, которые совместно используются каждым потоком. 2,область методасуществуетJDK1.7когда звонятпостоянное поколение,прибытьJDK1.8После этого от постоянной генерации отказались и заменили наметапространство(метапространство)
Если эта статья хоть немного вам поможет, то ставьте лайк, спасибо~
Наконец, если есть какие-либо недостатки или неточности, добро пожаловать на исправления и критику, большое спасибо! Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение и ответьте как можно скорее!
Приглашаю всех обратить внимание на мой публичный аккаунт, обсудить технологии вместе, стремиться к технологиям, заниматься технологиями, и вы будете друзьями, когда согласитесь...