Область данных времени выполнения JVM
Согласно спецификации JVM память JVM делится наСтек виртуальной машины, куча, область методов, счетчик программ, локальный стек методовПять частей.
Пространство памяти (область данных выполнения) можно разделить на две части в зависимости от того, является ли поток общим или нет.Общий поток — это область метода (область метода) и куча (куча), эксклюзивный поток — это стек виртуальной машины. (стек VM), локальный стек методов (собственный стек методов) и регистр ПК (регистр счетчика программ).
Пожалуйста, обратитесь к следующему рисунку для получения подробной информации:
площадь | обмен потоками | Будет ли память переполнена |
---|---|---|
счетчик команд | нет | Не буду |
стек виртуальных машин | нет | встреча |
собственный стек методов | нет | встреча |
куча | да | встреча |
область метода | да | встреча |
-
Стек виртуальной машины (приватный поток)
Каждый поток имеет частный стек, который создается при создании потока. В стеке есть нечто, называемое "фрейм стека".При выполнении каждого метода создается фрейм стека, в котором хранится таблица локальных переменных (базовые типы данных и ссылки на объекты), стек операндов, динамическое соединение и выход из метода. и другая информация. От вызова до завершения выполнения каждый метод соответствует размещению и извлечению фрейма стека в стеке виртуальной машины. Так называемый стек обычно относится к части таблицы локальных переменных в стеке виртуальной машины. Память, необходимая для таблицы локальных переменных, выделяется во время компиляции. Размер стека может быть фиксированным или динамически расширяться.Если расширение не может быть применено для достаточного количества памяти, возникает ошибка OutOfMemoryError. Когда глубина вызова стека превышает диапазон, разрешенный JVM, будет выдана ошибка StackOverflowError, но этот диапазон глубины не является постоянным значением Мы можем проверить этот результат с помощью следующей программы:// 栈溢出测试源码 package com.paddx.test.memory; /** * Created by root on 2/28/17. */ public class StackErrorMock { private static int index = 1; public void call() { index++; call(); } public static void main(String[] args) { StackErrorMock mock = new StackErrorMock(); try { mock.call(); } catch(Throwable e) { System.out.println("Stack deep: " + index); e.printStackTrace(); } } }
Запустив его три раза, можно увидеть, что глубина стека каждый раз разная, а результаты вывода следующие:
Глядя на три графика результатов, можно увидеть, что значение глубины стека каждый раз разное. Чтобы исследовать причину, вам нужно углубиться в исходный код JVM, чтобы обсудить его, поэтому я не буду здесь вдаваться в подробности. Помимо вышеперечисленных ошибок, в стеке виртуальной машины есть еще одна ошибка, то есть когда пространство не может быть выделено, будет выброшена ошибка OutOfMemoryError. Здесь следует отметить небольшую деталь: catch ловит Throwable, а не Exception, потому что ни StackOverflowError, ни OutOfMemoryError не являются подклассами Exception.
-
Стек собственных методов (приватный поток)
Подобно стеку виртуальной машины, он в основном обслуживает собственные методы, используемые виртуальной машиной. Также выдает StackOverflowError и OutOfMemoryError. -
Регистр ПК (приватный поток)
Регистр ПК, также называемый программным счетчиком. JVM поддерживает одновременное выполнение нескольких потоков, и каждый поток имеет собственный счетчик программ. Если в данный момент выполняется JVM-метод, в этом регистре хранится адрес исполняемой в данный момент инструкции, если выполняется нативный метод, то регистр ПК пуст. Эта область памяти является единственной областью виртуальной машины, в которой не указаны условия OutOfMemoryError. -
куча (общий поток)
Куча памяти — это часть, совместно используемая всеми потоками JVM, и создается при запуске виртуальной машины. Системные объекты приложений, тесно связанные с разработкой программ, хранятся в куче Java. Все объекты и массивы размещаются в куче. Эта часть пространства может быть восстановлена GC. Для генерационного GC куча тоже генерационная и является основной рабочей областью GC. Когда пространство не может быть выделено, будет выдан OutOfMemoryError. Ниже мы просто моделируем ситуацию переполнения динамической памяти:package com.paddx.test.memory; import java.util.ArrayList; import java.util.List; /** * Created by root on 2/28/17. */ public class HeapOomMock { public static void main(String[] args) { List<byte[]> list = new ArrayList<byte[]>(); int i = 0; boolean flag = true; while(flag) { try { i++; list.add(new byte[1024 * 1024]); // 每次增加1M大小的数组对象 }catch(Throwable e) { e.printStackTrace(); flag = false; System.out.println("Count = " + i); // 记录运行的次数 } } } }
Сначала настройте параметры запуска виртуальной машины среды выполнения:
Затем запустите код, и вывод будет следующим:
Обратите внимание, что здесь мы указали размер динамической памяти как 16M, поэтому Count=13 (это число не является фиксированным) отображается в этом месте, а почему это 13 или другие числа, это нужно судить в соответствии с GC бревно. -
Область метода (общий поток)
Область методов также используется всеми потоками. В основном используется для хранения информации о классе, пуле констант, данных метода, коде метода и т. д. Область метода логически является частью кучи, но для того, чтобы отличить ее от кучи, ее обычно называют «не куча».
Цели высвобождения памяти в этой области в основном связаны с высвобождением пула констант и выгрузкой типов.
Когда область метода не может удовлетворить требования к выделению памяти, создается исключение OutOfMemoryError.
В виртуальной машине HotSpot постоянное поколение используется для реализации области методов, а коллекция поколений GC расширяется до области методов, но легко столкнуться с проблемой переполнения памяти.
В JDK1.7 пул строковых констант в постоянном поколении был перемещен в кучу.
JDK1.8 отменяет постоянное поколение и вводит метапространство.
Вложения (стек, куча, взаимодействие области методов):
Ссылка на ссылку:
сегмент fault.com/ah/119000000…
blog.CSDN.net/universe_press…
woo woo woo.cn blog on.com/Meng Chunche…