В этой статье в основном подробно объясняется принцип его работы путем анализа стека, кучи и пула констант распределения памяти Java.
1. Прототип памяти виртуальной машины Java
Регистрация: мы не имеем контроля над программой. Стек: хранит базовые типы данных и ссылки на объекты, но сам объект хранится не в стеке, а в куче: хранятся данные, сгенерированные с помощью нового домена. : хранится в пуле констант статического члена, определенном с помощью static: хранит константы. Хранилище вне ОЗУ: постоянное пространство для хранения, например жесткий диск.
2. Постоянный пул
Пул констант относится к пулу констант, который определяется во время компиляции и сохраняется в скомпилированной памяти. Некоторые данные в файле класса. В дополнение к постоянным значениям (конечным), которые содержат различные базовые типы (такие как int, long и т. д.) и типы объектов (такие как String и массивы), определенные в коде, он также содержит некоторые символические ссылки в текстовой форме. , такой как:
1. Полные имена классов и интерфейсов;
2. Имя и дескриптор поля;
3. Методы, имена и дескрипторы.
Виртуальная машина должна поддерживать постоянный пул для каждого загруженного типа. Пул констант — это упорядоченный набор констант, используемых этим типом, включая прямые константы (строковые, целочисленные и с плавающей запятой) и символические ссылки на другие типы, поля и методы. Для строковых констант их значения находятся в пуле констант. Пул констант в JVM существует в виде таблицы в памяти. Для типа String существует таблица CONSTANT_String_info фиксированной длины, используемая для хранения литеральных строковых значений. Примечание. В этой таблице хранятся только литеральные строковые значения, а не символы. . Сказав это, вы должны иметь четкое представление о месте хранения строковых значений в пуле констант. Когда программа выполняется, пул констант будет храниться в области методов, а не в куче.
3. Стек в распределении памяти Java
Базовой единицей стека является кадр (или кадр стека): при каждом запуске потока Java виртуальная машина Java выделяет для этого потока стек Java. Когда поток выполняет определенный метод Java, он помещает кадр в стек Java. Этот кадр используется для хранения параметров, локальных переменных, операндов, результатов промежуточных операций и т. д. Когда этот метод завершит выполнение, кадр будет извлечен из стека. Все данные в стеке Java являются конфиденциальными, и никакой другой поток не может получить доступ к данным стека этого потока. Некоторые базовые типы переменных данных и переменных ссылок на объекты, определенные в функции, размещаются в стековой памяти функции. Когда переменная определена в блоке кода, Java выделяет для нее пространство памяти в стеке. Когда переменная выходит из области видимости, Java автоматически освобождает пространство памяти, выделенное для переменной, и это пространство памяти можно использовать немедленно. использоваться для других целей.
4. Куча при распределении памяти Java
Куча в виртуальной машине Java используется для хранения объектов и массивов, созданных новыми. Память, выделенная в куче, управляется механизмом автоматической сборки мусора виртуальной машины Java. Проще говоря, по сравнению со стеком, куча в основном используется для хранения объектов Java, а стек в основном используется для хранения ссылок на объекты. После того, как в куче сгенерирован массив или объект, также может быть создана специальная переменная. определено в стеке, так что значение этой переменной в стеке равно первому адресу массива или объекта в куче памяти. Эта переменная в стеке становится ссылочной переменной массива или объекта. Ссылочная переменная эквивалентна присвоению имени массиву или объекту. Затем вы можете использовать ссылочную переменную в стеке для доступа к массиву или объекту в куче программы. Ссылочная переменная эквивалентна присвоению имени массиву или объекту.
Ссылочные переменные — это обычные переменные, которые размещаются в стеке при определении. Ссылочные переменные освобождаются после того, как программа выходит за пределы своей области действия. Сами массивы и объекты размещаются в куче. Даже если программа выполняется вне блока кода, в котором находится оператор, использующий new для создания массива или объекта, память, занятая самим массивом и объектом, не будет освобождена. у объектов нет ссылочных переменных, указывающих на них, он становится мусором и больше не может использоваться, но все равно занимает пространство памяти и будет собран (освобожден) сборщиком мусора в неопределенное время позже. Это также причина, по которой Java занимает больше памяти. Фактически, переменные в стеке указывают на переменные в куче памяти. В Java это указатель!
Куча Java — это область данных времени выполнения, из которой объекты класса выделяют пространство. Эти объекты создаются с помощью таких инструкций, как new, newaray, anewarray и multianewarray, и они не требуют явного освобождения программного кода. Куча собирается с помощью сборки мусора. Ответственный, преимущество кучи заключается в том, что она может динамически выделять размер памяти, и время жизни не нужно сообщать компилятору заранее, поскольку она динамически выделяет память во время выполнения, а сборщик мусора Java автоматически соберет те, которые больше не используются. data, но недостатком является то, что из-за необходимости динамического выделения памяти во время выполнения скорость доступа низкая.
Преимущество стека в том, что скорость доступа выше, чем у кучи, уступая только регистру, и данные стека могут быть разделены. Но недостатком является то, что размер и время жизни данных, хранящихся в стеке, должны быть определены, а также отсутствует гибкость. В стеке в основном хранятся некоторые базовые типы переменных данных (int, short, long, byte, float, double, boolean, char) и дескрипторы объектов (ссылки).
Очень важной особенностью стека является возможность совместного использования данных, хранящихся в стеке. Предположим, мы также определяем:
int a=3; int b=3; Компилятор сначала обрабатывает int a = 3; сначала он создает ссылку на переменную a в стеке, а затем проверяет, есть ли в стеке значение 3. он установит 3 Store it in, а затем укажет a на 3. Затем обработайте int b = 3 после создания ссылочной переменной b, поскольку в стеке уже есть значение 3, b будет указывать непосредственно на 3; Таким образом, появляются a и b. Оба указывают на случай 3.
В это время, если a=4 установлено снова; тогда компилятор повторно проверит, есть ли в стеке значение 4. Если нет, он сохранит 4 и установит точку на 4, если она уже существует; прямо укажет на этот адрес. Следовательно, изменение значения a не повлияет на значение b.
Следует отметить, что этот вид совместного использования данных отличается от совместного использования ссылок двух объектов, указывающих на один объект одновременно, поскольку в этом случае модификация a не влияет на b, ее завершает компилятор, который выгодно экономить место. Если переменная ссылки на объект изменяет внутреннее состояние объекта, это повлияет на другую переменную ссылки на объект.