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

Общая память JVM разделена на следующие пять категорий:

  1. Область метода
  2. Площадь кучи
  3. Площадь стека
  4. регистры ПК
  5. Стеки собственных методов

Область метода:

  1. Для каждой JVM будет доступна одна область методов
  2. Область метода будет создана во время запуска JVM.
  3. Внутри области метода будут храниться двоичные данные уровня класса, включая статические.
  4. Константные пулы класса будут храниться внутри области методов.
  5. К области метода могут одновременно обращаться несколько потоков, поэтому она не является потокобезопасной.

Область кучи:

  1. Для каждой JVM доступна одна область кучи
  2. Область кучи будет создана во время запуска JVM.
  3. Объекты и соответствующие переменные экземпляра будут храниться в области кучи.
  4. Каждый массив в java является только объектом, поэтому массивы также будут храниться в области кучи.
  5. К области кучи могут обращаться несколько потоков, поэтому данные, хранящиеся в памяти кучи, не являются потокобезопасными.
  6. Область кучи не обязательно должна быть непрерывной.

Программа для отображения статистики динамической памяти:

Java-приложение может взаимодействовать с JVM с помощью объекта Runtime, класс Runtime, представленный в пакете java.lang, является одноэлементным классом, мы можем создать объект Runtime следующим образом.

Время выполнения r = Runtime.getRuntime();

Как только мы получили объект времени выполнения, мы можем вызвать следующие методы для этого объекта.

maxMemory() : возвращает количество байтов максимальной памяти, выделенной для кучи

freeMemory(): возвращает количество байтов свободной памяти в куче.

totalMemory(): возвращает количество байтов общей памяти, выделенной для кучи (исходная память)

импортировать java.lang.ClassLoader;

открытый класс HeapStatistics{

public static void main(String[] args) {

Время выполнения r = время выполнения.getRuntime();

System.out.println("Свободная память: "+r.freeMemory()/(1024*1024));

System.out.println("Максимальная память: "+r.maxMemory()/(1024*1024));

System.out.println("Общая память: "+r.totalMemory()/(1024*1024));

System.out.println («Потребляемая память: »+r.totalMemory() — r.freeMemory()/(1024*1024));

}

}

Вывод в МБ:

Свободная память: 240

Максимальная память: 3609

Всего памяти: 243

Потребляемая память: 2

Как установить максимальный и минимальный размер кучи?

Память кучи — это ограниченная память, но в зависимости от наших требований мы можем установить максимальный и минимальный размер кучи. т.е. мы можем увеличить или уменьшить размер кучи в зависимости от наших требований. Мы можем использовать следующие флаги с командой java.

-Xmx установить максимальный размер кучи (maxMemory)

Например: - java -Xmx512m HeapStatistics

Эта команда установит максимальный размер кучи как 512 МБ.

-Xms для установки минимального размера кучи()

Например: - java -Xms64m HeapStatistics

Эта команда установит минимальный размер кучи как 64 МБ, т.е. totalMemory

Область памяти стека: для каждого потока JVM создает отдельный стек во время создания потока. Каждый вызов метода, выполняемый этим потоком, будет храниться в стеке, включая локальные переменные, после завершения метода соответствующая запись из стека будет удалена, после завершения всех вызовов метода стек станет пустым, и этот пустой стек будет уничтожается JVM непосредственно перед завершением потока. Каждая запись в стеке называется кадром стека или записью активации.

Данные, хранящиеся в стеке, доступны только для соответствующего потока и недоступны для остальных потоков, поэтому эти данные являются потокобезопасными.

Структура кадра стека:

Массив локальных переменных: содержит все параметры и локальные переменные метода. Каждый слот в массиве занимает 4 байта. Значения типа int, float и reference занимают одну запись в массиве. Значения double и long занимают две последовательные записи в массиве. byte , short и char будут преобразованы в тип int перед сохранением и займут 1 слот, но способ хранения логических значений варьируется от JVM к JVM, но большинство JVM используют один слот для логических значений.

Стек операндов: JVM использует стек операндов в качестве рабочей области, некоторые инструкции могут помещать значения в стек операндов, а некоторые инструкции могут извлекать значения из стека операндов, а некоторые инструкции могут выполнять требуемые операции.

Данные кадра. Данные кадра содержат все символические ссылки, относящиеся к этому методу, а также ссылку на таблицу исключений, которая предоставляет соответствующую информацию о блоке перехвата в случае исключений.

Регистры ПК: для каждого потока будет создан отдельный регистр ПК во время создания потока. Регистры ПК содержат адрес текущей выполняемой инструкции, после автоматического завершения выполнения инструкции регистр ПК будет увеличен для хранения адреса следующая инструкция.

Стеки нативных методов. Для каждого потока JVM создаст отдельный стек нативных методов, все вызовы нативных методов, вызванные потоком, будут храниться в соответствующем стеке нативных методов.

Вывод: Область метода, область кучи и область стека считаются важными областями памяти для программиста. Область метода и область кучи относятся к JVM, тогда как область стека, регистры ПК и собственные стеки методов относятся к потоку.

Статические переменные будут храниться в области метода, переменная экземпляра будет храниться в области кучи, локальные переменные будут храниться в области стека.

Спасибо.