Обязательной книгой для изучения JVM, несомненно, является книга «Углубленное понимание виртуальной машины Java», В книге модель области данных во время выполнения описывается следующим образом:
Здесь мы сосредоточимся только на HotSpot VM, которая является виртуальной машиной в OracleJDK и OpenJDK и в настоящее время является наиболее широко используемой виртуальной машиной Java. До JDK7 такая модель была правильной. Но когда дело доходит до JDK8, были сделаны некоторые оптимизации, такие как красная часть значка.
Что такое область методов, что такое постоянное поколение и что такое постоянный пул времени выполнения
- «Область методов» — это область, совместно используемая потоками, которая используется для хранения данных, таких как информация о классе, константы и статические переменные, которые были загружены виртуальной машиной. Прежде всего, нам нужно знать, что область методов — это спецификация JVM и концепция, и конкретная реализация этой области методов реализуется каждым производителем виртуальной машины.
- «Постоянная генерация» — это реализация области методов виртуальной машины HotSpot, и она доступна только для HotSpot.
- «Пул констант времени выполнения» является частью области методов. Используется для хранения различных литералов и символических ссылок, сгенерированных во время компиляции. Его характеристика динамична.
Оптимизация 1: пул строковых констант переносится из постоянного поколения в кучу Java.
Из-за динамического характера пула констант большое количество строковых констант будет создано в пуле констант времени выполнения во время выполнения программы.В это время, если они помещены в постоянное поколение, размер постоянного поколения не может быть правильно установлен, что может привести к проблемам с производительностью и переполнению памяти. Следующий пример доказывает, что в JDK8 пул строковых констант был помещен в кучу:
Функция метода String.intern() состоит в том, чтобы вернуть ссылку на строку, которая ссылается на строку (литерал) в пуле строковых констант. Давайте сначала проверим этот метод:
public class StringConstantsPoolTest {
public static void main(String[] args) {
String str = "abc"; // str存储在常量池
String str2 = new String("abc"); // str2 存储在堆中
System.out.println(str == str2); // 结果为false ,堆中的引用并不等于常量池中的引用
str2 = str2.intern(); // 获取str2在常量池中的引用
System.out.println(str == str2);
}
}
Результат выглядит следующим образом:
Докажите, что метод String.innern () возвращает ссылку в постоянном пуле. Следующие проверяют, что строковый постоянный пул находится в куче: Установить параметры JVM:
-Xms10m -Xmx10m -XX:-UseGCOverheadLimit
public static void main(String[] args) {
List<String> list = new ArrayList();
int i = 0;
while(true){
list.add(String.valueOf(i++).intern());
}
}
Результат выглядит следующим образом:
Мы видим, что в это время сообщается о переполнении памяти кучи Java, что указывает на то, что пул строковых констант находится в куче.Обратите внимание, что в это время в кучу передается только пул строковых констант, ноПул констант среды выполнения все еще находится в области методов.
Оптимизация 2: удалить постоянное поколение и ввести «Метапространство».
Зачем удалять постоянное поколение?
- Размер области метода трудно установить, что может привести к переполнению памяти.. Постоянное поколение будет хранить соответствующую информацию класса. Как правило, размер этой информации может быть определен во время компиляции. Однако, если он находится в некоторых приложениях, которые необходимо динамически генерировать большое количество классов, таких как: динамический прокси-прокси весны, большое количество страниц JSP или динамически сгенерированные страницы JSP и т. Д., Поскольку размер области метода должен быть Выделено в начале, это может быть трудно определить. Размер, склонны к переполнению памяти
- GC сложный и неэффективный. Область методов хранит метаданные о классе и различные константы, а целью восстановления памяти должна быть выгрузка этих типов и восстановление констант. Однако, поскольку на эти данные ссылаются экземпляры класса, условия выгрузки становятся сложными и строгими, а неправильная переработка приведет к тому, что экземпляры класса в куче потеряют информацию метаданных и константную информацию. Таким образом, освобождение памяти области методов — непростая и неэффективная вещь.
- Упрощение интеграции HotSpot JVM и JRockit VM. JRockit не имеет области методов, и удаление постоянного поколения может облегчить интеграцию HotSpot JVM с JRockit VM.
Что такое метапространство и зачем оно введено
Суть метапространства аналогична постоянному поколению и представляет собой реализацию области методов в спецификации JVM. Но самая большая разница между метапространством и постоянным поколением заключается в том, что метапространство находится не в виртуальной машине, а использует локальную память. Поэтому по умолчанию размер метапространстваОграничено только локальной памятью.
Особенности метапространства:
- У каждого погрузчика есть специальное место для хранения.
- Класс не перерабатывается индивидуально.
- Положения объектов в метапространстве фиксированы.
- Если выяснится, что загрузчик выжил, соответствующее пространство будет восстановлено по всему пространству.
Суммировать
Окончательная модель области данных времени выполнения JVM (HotSpot) выглядит следующим образом: