❝Лично я считаю, что в JVM есть много знаний, которые нужно понять и запомнить, а код не особенно велик, в основном для пост-настройки, что требует большого опыта. Тем не менее, JVM необходимо глубоко понимать.
❞
контурная карта
структура файла класса
Обзор
В Java код, который понимает JVM, называется字节码
(т.е. расширение.class
файл), он не нацелен на какой-либо конкретный процессор, а только на виртуальные машины. Язык Java в определенной степени решает проблему низкой эффективности исполнения традиционных интерпретируемых языков за счет байт-кодов, и в то же время сохраняет переносимость интерпретируемых языков. Таким образом, Java-программы более эффективны для запуска, а поскольку байт-коды не являются специфическими для одной конкретной машины, Java-программы могут работать на компьютерах со многими различными операционными системами без перекомпиляции.
"Можно сказать.class
Файлы являются важным связующим звеном между различными языками в виртуальной машине Java и одной из причин, почему важно поддерживать кроссплатформенность Java."
структура файла класса
ClassFile {
u4 magic; // 魔数 Class 文件的标志 这都没话可说的
u2 minor_version;//Class 的小版本号
u2 major_version;//Class 的大版本号
u2 constant_pool_count;//常量池的数量
cp_info constant_pool[constant_pool_count-1];//常量池 待会说
u2 access_flags;//Class 的访问标记
u2 this_class;//当前类
u2 super_class;//父类
u2 interfaces_count;//接口
u2 interfaces[interfaces_count];//一个类可以实现多个接口
u2 fields_count;//Class 文件的字段属性
field_info fields[fields_count];//一个类会可以有个字段 描述接口或类中声明的变量 但不包括在方法内部声明的局部变量.
u2 methods_count;//Class 文件的方法数量
method_info methods[methods_count];//一个类可以有个多个方法 和字段表性质一样
u2 attributes_count;//此类的属性表中的属性数
attribute_info attributes[attributes_count];//属性表集合
}
статический постоянный пул
Пул констант в основном хранит две константы:"Буквальные и символические ссылки". Литералы относительно близки к константным понятиям на уровне языка Java, таким как текстовые строки, постоянные значения, объявленные как окончательные, и т. д. Символические ссылки относятся к концепции принципов компиляции. Он включает в себя следующие три типа констант:
- Полные имена классов и интерфейсов
- Имена полей и дескрипторы
- имя и дескриптор метода
Преимущества постоянного пула: Постоянный пул позволяет избежать частого создания и уничтожения объектов и влияет на производительность системы, которая реализует совместное использование объектов.
Например: пул строковых констант, поместить все строковые литералы в пул констант во время компиляции.
- Экономия места в памяти: все идентичные строковые константы в пуле констант объединяются, чтобы занимать только одно место.
- Экономит время выполнения: == быстрее, чем equals() при сравнении строк. Для двух ссылочных переменных используйте только ==, чтобы определить, равны ли ссылки, а затем вы можете определить, равны ли фактические значения.
Статический пул констант используется для хранения всех видов сгенерированных во время компиляции"Буквальные и символические ссылки", эта часть содержимого будет храниться в области метода после загрузки класса"постоянный пул времени выполнения"середина. Символическая ссылка на самом деле ссылается на строку в пуле констант, но"Символьные ссылки не хранят строки напрямую, а сохраняют индекс строк в пуле констант.".
Когда файл класса загружен, виртуальная машина Java передаст содержимое статического пула констант в пул констант времени выполнения."Символические ссылки частично преобразуются в прямые ссылки"Например, статический метод или частный метод класса, конструктор экземпляра, метод родительского класса, это потому, что эти методы не могут быть переопределены другими версиями, поэтому символическая ссылка может быть преобразована в прямую ссылку при загрузке, в то время как другие Некоторые методы преобразуются из символических ссылок в прямые ссылки при первом вызове метода.
постоянный пул времени выполнения
Пул констант времени выполнения"область метода"часть. Для пула констант времени выполнения Спецификация виртуальной машины Java не требует никаких подробностей, и виртуальные машины, реализованные разными поставщиками, могут реализовывать эту область памяти в соответствии со своими потребностями. Однако, как правило, в дополнение к сохранению символических ссылок, описанных в файле класса, преобразованные прямые ссылки также сохраняются в пуле констант времени выполнения.
Есть еще одна важная особенность пула констант времени выполнения:"динамизм". Java требует, чтобы содержимое пула констант во время компиляции могло попасть в пул констант во время выполнения, а константы, сгенерированные во время выполнения, также могли быть помещены в пул. Наиболее часто используется метод intern() класса String.
Поскольку пул констант времени выполнения является частью области методов, он, естественно, ограничен памятью области методов."OutOfMemoryError"аномальный.
Пул строковых констант
Пул строковых констант существует в пуле констант времени выполнения (в пуле констант времени выполнения до JDK7 он был перенесен в кучу в JDK7).
Существование пула строковых констант позволяет JVM повысить производительность и снизить нагрузку на память.
- Всякий раз, когда мы используем литерал (String s="1";) для создания строковой константы, JVM сначала проверяет пул строковых констант, если строка уже существует в пуле констант, а затем присваивает адрес строкового объекта. Дайте ссылку s (ссылка s в стеке Java. Если строка не существует в пуле констант, строка создается и помещается в пул констант, а адрес объекта строки присваивается ссылке s (ссылка s в стеке Java ).
- Всякий раз, когда мы используем ключевое слово new (String s=new String("1");) для создания строковой константы, JVM сначала проверяет пул строковых констант, если строка уже существует в пуле констант, ее больше нет в строка символов Пул строковых констант создает строковый объект и непосредственно создает копию объекта в куче, а затем присваивает адрес объекта в куче ссылке s. Если строка не существует в пуле констант , строка будет создана и помещена в пул констант, затем создайте копию объекта в куче и назначьте адрес объекта в куче ссылке s.
отношения между тремя
Когда JVM выполняет определенный класс, он должен пройти загрузку, подключение и инициализацию, а подключение включает в себя три этапа проверки, подготовки и анализа.
Статический пул констант используется для хранения различных литералов и символических ссылок, сгенерированных во время компиляции, и когда класс загружается в память, jvm будет хранить содержимое статического пула констант в пуле констант времени выполнения. В пуле строковых констант хранятся ссылочные значения, которые существуют в пуле констант времени выполнения.
изменение версии
1.6
-
Статический постоянный пул находится в файле класса.
-
Пул констант времени выполнения находится в области Perm Gen (то есть в области методов). (Так называемая область метода является логической частью кучи Java. Чтобы отличить ее от кучи Java, ее еще называют некучей (Non-Heap), тогда еще область Perm Gen (постоянная генерация) рассматривается как часть области реализации метода.)
-
Пул строковых констант находится в пуле констант времени выполнения.
1.7
- Статический постоянный пул находится в файле класса.
- Пул констант времени выполнения по-прежнему находится в области Perm Gen (то есть в области методов). В версии JDK7 работа по передаче постоянного поколения уже началась, например, ссылки на символы (Symbols) переносятся в нативную кучу; литералы (интернированные строки) передаются в кучу java; статические переменные класса (статика класса) передаются в куча Java. Но пул констант времени выполнения все еще существует, но передается много контента, и он хранит только переданные ссылки. Некоторые методы или коды, циркулирующие в Интернете для проверки передачи пула констант во время выполнения, на самом деле являются тестами передачи пула констант строк.
- Пул строковых констант выделяется основной части кучи Java (известной как молодое и старое поколения). То есть пул строковых констант отделен от пула констант времени выполнения.
1.8
- Статический постоянный пул находится в файле класса.
- JVM переместила пул констант времени выполнения из области методов и открыла область в куче Java (Heap) для хранения пула констант времени выполнения. При этом постоянное поколение удаляется и заменяется метапространством. Метапространство находится не в виртуальной машине, а использует локальную память. Поэтому по умолчанию размер метапространства ограничен только локальной памятью. Он в основном используется для хранения некоторых метаданных.
- Пул строковых констант существует в куче Java.
процесс загрузки класса
Система загружает файлы типа Class в три основных этапа:"Загрузить->Подключить->Инициализировать". Процесс подключения можно разделить на три этапа:"Проверить -> Подготовить -> Разобрать".
нагрузка
Первый шаг в процессе загрузки класса в основном завершает следующие три вещи:
- Получите двоичный поток байтов, определяющий этот класс по его полному имени класса
- Преобразуйте статическую структуру хранения, представленную потоком байтов, в структуру данных времени выполнения области метода.
- Создайте объект класса, представляющий класс в памяти, в качестве записи доступа к этим данным в области методов.
Части фазы загрузки и фазы связывания чередуются, и фаза связывания может уже начаться до завершения фазы загрузки.
проверять
- Проверка формата файла: в основном проверьте, стандартизирован ли файл класса и т. д.
- Проверка метаданных: информационно-семантический анализ описаний байткодов и т.д.
- Проверка байт-кода: убедитесь, что семантика в порядке.
- Проверка символьной ссылки: убедитесь, что действие разрешения может быть выполнено.
Подготовить
"Фаза подготовки — это фаза, на которой формально выделяется память для переменных класса и устанавливаются начальные значения для переменных класса.", эта память будет выделена в области методов. На этом этапе есть несколько замечаний:
- В настоящее время выделение памяти включает только переменные класса (статические), а не переменные экземпляра.Переменные экземпляра будут выделены в куче Java вместе с объектом при создании экземпляра объекта.
- Установленное здесь начальное значение «обычно» является нулевым значением по умолчанию для типа данных (например, 0, 0L, null, false и т. д.), например, мы определяем
public static int value=111
, то начальное значение переменной value на этапе подготовки равно 0 вместо 111 (оно будет скопировано только на этапе инициализации). Особые случаи: например, добавление ключевого слова fianl к переменной значения.public static final int value=111
, то значение фазы подготовки копируется в 111.
Разобрать
Фаза разрешения — это процесс, посредством которого виртуальная машина заменяет символические ссылки в пуле констант прямыми ссылками. Действие синтаксического анализа в основном выполняется для 7 типов символических ссылок, таких как класс или интерфейс, поле, метод класса, метод интерфейса, тип метода, дескриптор метода и квалификатор вызова.
Символическая ссылка — это набор символов для описания цели, который может быть любым литералом."прямая цитата"Является указателем непосредственно на цель, относительным смещением или маркером, который косвенно расположен на цели. Когда программа действительно работает, одних только символических ссылок недостаточно, например: когда программа выполняет метод, система должна точно знать, где этот метод находится. Виртуальная машина Java подготавливает таблицу методов для каждого класса для хранения всех методов класса. Когда вам нужно вызвать метод класса, вы можете вызвать метод напрямую, если вы знаете смещение метода в боковой таблице. Разрешив ссылку на символ операции, ее можно напрямую преобразовать в позицию целевого метода в таблице методов класса, чтобы метод можно было вызвать.
Подводя итог, можно сказать, что фаза синтаксического анализа — это процесс, в котором виртуальная машина заменяет символические ссылки в пуле констант прямыми ссылками, то есть для получения указателей или смещений классов, полей и методов в памяти.
инициализация
Инициализация — это последний шаг загрузки класса, а также фактическое выполнение программного кода Java (байт-кода), определенного в классе.Фаза инициализации заключается в выполнении конструктора класса.<clinit> ()
процесс метода.
за<clinit>()
Вызовы методов, виртуальная машина сама обеспечивает свою безопасность в многопоточной среде. потому что<clinit>()
Метод является потокобезопасным с блокировками, поэтому инициализация класса в многопоточной среде может привести к взаимоблокировкам, и такие взаимоблокировки трудно обнаружить.
Для фазы инициализации виртуальная машина строго указывает, что есть только 5 случаев, в которых класс должен быть инициализирован:
- При встрече с четырьмя прямыми инструкциями кода new , getstatic, putstatic или invokestatic, такими как создание нового класса, чтение статического поля (без окончательного изменения) или вызов статического метода класса.
- использовать
java.lang.reflect
Когда метод пакета делает рефлексивный вызов класса, если класс не инициализирован, его инициализацию необходимо запустить. - Инициализируйте класс, если его родительский класс не был инициализирован, сначала инициируйте инициализацию родительского класса.
- Когда запускается виртуальная машина, пользователю необходимо определить основной класс (тот, который содержит основной метод) для выполнения, и виртуальная машина сначала инициализирует этот класс.
- При использовании динамического динамического языка JDK1.7, если последней проанализированной структурой экземпляра MethodHandle является дескриптор метода REF_getStatic, REF_putStatic, REF_invokeStatic, и этот дескриптор не инициализирован, его необходимо сначала инициализировать с помощью триггера.
загрузчик классов
В JVM встроено три важных загрузчика классов.За исключением BootstrapClassLoader, другие загрузчики классов реализованы в Java,java.lang.ClassLoader
:
-
"BootstrapClassLoader (загрузчик загрузочного класса)": класс загрузки верхнего уровня, реализованный на C++, отвечает за загрузку
%JAVA_HOME%/lib
Пакеты и классы jar в каталоге либо являются, либо-Xbootclasspath
Все классы в пути, указанном параметром. -
"ExtensionClassLoader (загрузчик класса расширения)": В основном отвечает за загрузку каталога
%JRE_HOME%/lib/ext
пакеты и классы jar в каталоге илиjava.ext.dirs
Пакет jar по пути, указанному в системной переменной. - "AppClassLoader (загрузчик классов приложений)": загрузчик для наших пользователей, отвечающий за загрузку всех пакетов и классов jar в рамках текущего пути к классам приложения.
родительская делегация
У каждого класса есть соответствующий ему загрузчик классов. ClassLoder в системе будет использоваться по умолчанию при совместной работе"Модель родительского делегирования". То есть при загрузке класса система сначала определит, был ли загружен текущий класс. Классы, которые уже были загружены, будут возвращены напрямую, в противном случае будет предпринята попытка загрузки. При загрузке запрос сначала делегируется загрузчику родительского классаloadClass()
обработка, поэтому все запросы должны в конечном итоге направляться в загрузчик классов запуска верхнего уровняBootstrapClassLoader
середина. Когда загрузчик родительского класса не может с этим справиться, вам решать. Когда загрузчик родительского класса имеет значение null, используется загрузчик запускаемого класса.BootstrapClassLoader
как загрузчик родительского класса.
public class ClassLoaderDemo {
public static void main(String[] args) {
System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());
System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());
System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());
}
}
// ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2
// The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586
// The GrandParent of ClassLodarDemo's ClassLoader is null
AppClassLoader
Родительский загрузчик классовExtClassLoader
ExtClassLoader
Родительский загрузчик классов имеет значение null,"ноль не значитExtClassLoader
Загрузчика родительского класса нет, ноBootstrapClassLoader
".
На самом деле, перевод родителей легко может быть неправильно понят другими. Мы обычно понимаем, что оба родителя являются родителями. Родители здесь больше выражают «поколение родителей». Это не означает, что на самом деле существует Mother ClassLoader и Отец ClassLoader . Кроме того, отношение «родитель-потомок» между загрузчиками классов не отражается наследованием, а определяется «приоритетом».
"Преимущества родительского делегирования":
Модель родительского делегирования обеспечивает стабильную работу Java-программ и позволяет избежать повторной загрузки классов (способ, которым JVM различает разные классы, основан не только на имени класса, один и тот же файл класса загружается разными загрузчиками классов, в результате чего получается два разных класса). ), а также гарантирует, что основной API Java не будет изменен. Проблемы могут возникнуть, если родительская модель делегирования не используется, но каждый загрузчик классов загружает сам себя.Например, если мы напишем класс с именемjava.lang.Object
class, то при запуске программы в системе появится несколько разныхObject
Добрый.
пользовательский загрузчик классов
КромеBootstrapClassLoader
Другие загрузчики классов реализованы на Java, и все они наследуются отjava.lang.ClassLoader
. Если мы хотим настроить наш собственный загрузчик классов, очевидно, нам нужно наследоватьClassLoader
.
память jvm (область выполнения)
До 1.8
После 1.8
Резюме согласно 1.8
"Частная тема:"
- счетчик команд
- стек виртуальных машин
- собственный стек методов
"Разделено по темам:"
- куча
- Прямая память (часть нерабочей области данных)
счетчик команд
Грубо говоря
- Интерпретатор байт-кода последовательно считывает инструкции, изменяя программный счетчик, чтобы реализовать управление потоком кода, например: последовательное выполнение, выбор, цикл, обработка исключений.
- В случае многопоточности счетчик программ используется для записи позиции выполнения текущего потока, чтобы, когда поток переключается обратно, он мог знать, где поток выполнялся в последний раз.
"Примечание. Счетчик программ — это единственная область памяти, которая не получает ошибку OutOfMemoryError, ее время жизни создается при создании потока и умирает при завершении потока."
Стек виртуальной машины Java
Как и счетчик программ, стек виртуальной машины Java представляет собой поток."частный"Да, он имеет тот же жизненный цикл, что и поток, и описывает Java."Модель памяти выполнения метода", данные для каждого вызова метода проходят через стек.
"Память Java можно грубо разделить на память кучи (Heap) и память стека (Stack), где стек — это стек виртуальной машины или часть таблицы локальных переменных стека виртуальной машины."
- таблица локальных переменных
- стек операндов
- 8 основных типов
- Ссылка на объект: это может быть указатель на начальный адрес объекта или указатель на дескриптор, представляющий объект, или другое место, связанное с объектом.
- динамическая ссылка
- экспорт метода
"В стеке виртуальной машины Java есть два исключения: StackOverFlowError и OutOfMemoryError."
- "StackOverFlowError:"Если объем памяти стека виртуальной машины Java не допускает динамического расширения, когда глубина стека запросов потока превышает максимальную глубину текущего стека виртуальной машины Java, будет выдано исключение StackOverFlowError.
- "OutOfMemoryError:"Если размер памяти стека виртуальной машины Java допускает динамическое расширение, а когда поток запрашивает стек, память заканчивается и не может быть расширена динамически, будет выдано исключение OutOfMemoryError.
Стек виртуальной машины Java также является частным потоком, и каждый поток имеет свой собственный стек виртуальной машины Java, который создается при создании потока и умирает, когда поток умирает.
Стек Java можно сравнить со стеком в структуре данных. Основное содержимое, хранящееся в стеке Java, — это кадр стека. Каждый вызов функции будет иметь соответствующий кадр стека, помещаемый в стек Java. После каждого вызова функции кадр стека будет помещен в стек Java.
собственный стек методов
Это очень похоже на роль, которую играет стек виртуальной машины, разница заключается в следующем:"Стек виртуальной машины служит виртуальной машине для выполнения методов Java (то есть байт-кода), в то время как собственный стек методов обслуживает собственные методы, используемые виртуальной машиной."Другие аналогичны виртуальной машине Java.
куча
Самая большая часть памяти, управляемая виртуальной машиной Java, куча Java — это область памяти, совместно используемая всеми потоками, создаваемая при запуске виртуальной машины."Единственная цель этой области памяти — хранить экземпляры объектов, почти все экземпляры объектов и массивы выделяются здесь памятью."
Куча Java — это основная область, управляемая сборщиком мусора, поэтому она также называется"Куча мусора".С точки зрения сборки мусора, поскольку сборщик в основном использует алгоритм сборки мусора поколений, куча Java также может быть подразделена на: новое поколение и старое поколение: более подробно: пространство Eden, From Survivor, To Survivor и т. д. . . ."Целью дальнейшего деления является более эффективное использование памяти или ее более быстрое выделение."
Область eden, область s0 («От») и область s1 («Кому»), показанные на рисунке выше, относятся к новому поколению, а область с тентами принадлежит к старому поколению. В большинстве случаев объект сначала будет размещен в районе Эдема.После сборки мусора нового поколения, если объект еще жив, он войдет в s1 ("До"), и возраст объекта также увеличится на 1 (Область Эдема -> Область выжившего. После того, как начальный возраст объекта станет равным 1), когда его возраст увеличится до определенного уровня (по умолчанию 15 лет), он будет переведен в старое поколение. Порог возраста для перевода объекта в старое поколение, который можно передать через параметр-XX:MaxTenuringThreshold
устанавливать. После этого GC область Эдема и область "От" были опустошены. В это время «От» и «Кому» поменяются ролями, то есть новый «Кому» — это «От» перед последним GC, а новый «От» — это «Кому» перед последним GC. В любом случае, область выживших с именем To гарантированно пуста. Незначительный GC будет повторять этот процесс до тех пор, пока не будет заполнена область «Кому», а после заполнения области «Кому» все объекты будут перемещены в старое поколение.
область метода
Как и куча Java, область методов — это область памяти, совместно используемая каждым потоком, которая используется для хранения таких данных, как информация о классе, константы, статические переменные и код, скомпилированный компилятором реального времени, которые были загружены виртуальной машиной. . Хотя спецификация виртуальной машины Java описывает область методов как логическую часть кучи, у нее есть псевдоним, называемый"Без кучи", цель должна состоять в том, чтобы отличить его от кучи Java.
В JDK 1.8 область методов (постоянная генерация HotSpot) была полностью удалена (JDK 1.7 уже запущена) и заменена метапространством, которое использует прямую память.
постоянный пул времени выполнения
Пул констант времени выполнения является частью области методов. В Class файле, помимо информации описания версии класса, поля, метода, интерфейса и т.д., есть также константная информация пула (используется для хранения различных литералов и символьных ссылок, сгенерированных при компиляции), а символьные ссылки заменены по прямым ссылкам. JVM JDK1.8 и более поздних версий переместили пул констант времени выполнения из области методов и открыли область в куче Java (Heap) для хранения пула констант времени выполнения.
прямая память
Прямая память не является частью области данных среды выполнения виртуальной машины и не является областью памяти, определенной в спецификации виртуальной машины, но эта часть памяти также часто используется. И это также может вызвать исключения OutOfMemoryError. Выделение собственной прямой памяти не будет ограничено кучей Java, но, поскольку это память, оно будет ограничено общим объемом собственной памяти и адресным пространством процессора.
создание объекта
-
Проверка загрузки класса, когда виртуальная машина встречает новую инструкцию, она сначала проверяет, могут ли параметры этой инструкции найти символическую ссылку этого класса в пуле констант, и проверяет, был ли загружен класс, представленный этой символической ссылкой, разрешено и инициализировано. Если нет, то сначала необходимо выполнить соответствующий процесс загрузки класса.
-
выделить память в"проверка загрузки класса"После прохождения следующая виртуальная машина будет новым объектом"Выделить память". Размер требуемой объекту памяти можно определить после загрузки класса, а задача выделения места под объект эквивалентна делению блока памяти определенного размера из кучи Java."Распределение"имеют"«Столкновение указателей»"а также"«Свободный список»"два,"Выбор метода распределения определяется тем, является ли куча Java обычной или нет, а является ли куча Java обычной или нет, определяется тем, имеет ли используемый сборщик мусора функцию уплотнения.".
-
"Два способа распределения памяти: (дополнительный контент, необходимо освоить)"
- Какой из двух вышеперечисленных методов выбрать, зависит от того, является ли память кучи Java обычной или нет. Является ли память кучи Java регулярной, зависит от того, является ли алгоритм сборщика сборщика мусора "маркировать-очистка" или "маркировать-очищать" (также известный как "маркировать-сжатие"). Стоит отметить, что память алгоритма копирования также регулярно
-
Справочник - JavaGuide - Распределение памяти
-
"Проблема параллелизма выделения памяти (дополнительный контент, необходимо освоить)"
- "CAS+ошибка повторной попытки:"CAS — это реализация оптимистической блокировки. Так называемая оптимистическая блокировка заключается в том, чтобы завершить операцию без блокировки каждый раз, но предполагая, что конфликта нет, и повторять попытку до тех пор, пока она не увенчается успехом, если она не удалась из-за конфликта."Виртуальная машина использует CAS в сочетании с неудачной повторной попыткой, чтобы обеспечить атомарность операций обновления."
- "TLAB:"Заранее выделяйте часть памяти в области Eden для каждого потока.Когда JVM выделяет память для объекта в потоке, она сначала выделяет его в TLAB.Когда объект больше, чем оставшаяся память в TLAB или памяти TLAB исчерпан, указанная выше память снова используется.CAS для выделения памяти
-
-
Инициализировать нулевое значение.После завершения выделения памяти виртуальная машина должна инициализировать выделенное пространство памяти до нулевого значения (за исключением заголовка объекта).Этот шаг гарантирует, что поле экземпляра объекта может быть непосредственно назначено в Java code без присвоения начального значения, с помощью которого программа может получить доступ к нулевому значению, соответствующему типу данных этих полей.
-
После установки заголовка объекта и инициализации нулевого значения,"Виртуальной машине необходимо произвести необходимые настройки объекта"Например, этот объект является экземпляром этого класса, как найти информацию о метаданных класса, хэш-код объекта, возраст создания GC объекта и т. д."Эта информация хранится в заголовке объекта."Кроме того, в зависимости от текущего состояния виртуальной машины, например, включения блокировки смещения и т. д., заголовок объекта будет установлен по-разному.
-
Выполните метод init После завершения вышеуказанной работы с точки зрения виртуальной машины был создан новый объект, но с точки зрения программы Java создание объекта только началось.
方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行
метод, объект инициализируется в соответствии с пожеланиями программиста, так что полностью создается действительно пригодный для использования объект.
расположение памяти
В виртуальной машине Hotspot расположение объектов в памяти можно разделить на 3 области:"заголовок объекта","данные экземпляра"а также"Выровнять отступы".
"Заголовок объекта виртуальной машины Hotspot состоит из двух частей информации","Первая часть используется для хранения собственных данных времени выполнения самого объекта."(хэш-код, возраст генерации сборщика мусора, флаги состояния блокировки и т. д.),"Другая часть - это указатель типа", то есть указатель объекта на его метаданные класса, и виртуальная машина использует этот указатель, чтобы определить, что объект является экземпляром этого класса.
"Часть данных экземпляра — это достоверная информация, которую фактически хранит объект.", но и различные типы содержимого полей, определенные в программе.
"Заполнение выравнивания не обязательно существует и не имеет особого значения, а служит только заполнителем."Поскольку система автоматического управления памятью виртуальной машины Hotspot требует, чтобы начальный адрес объекта был целым числом, кратным 8 байтам, иными словами, размер объекта должен быть целым числом, кратным 8 байтам. Часть заголовка объекта точно кратна 8 байтам (1 или 2 раза), поэтому, когда часть данных экземпляра объекта не выровнена, ее необходимо заполнить путем заполнения выравнивания.
как осуществляется доступ к объектам
Создание объекта означает использование объекта, и наша программа на Java работает с конкретным объектом в куче через справочные данные в стеке. Метод доступа к объекту определяется реализацией виртуальной машины. Текущие основные методы доступа:"① Используйте ручку"а также"②Прямой указатель"Два вида:
использовать ручку
Если используется дескриптор, часть памяти будет разделена в куче Java в качестве пула дескрипторов, а адрес дескриптора объекта хранится в ссылке, а дескриптор содержит конкретную информацию об адресе данных и типе экземпляра объекта. данные;
прямой указатель
Если используется доступ с прямым указателем, то макет объекта кучи Java должен учитывать, как разместить соответствующую информацию данных типа доступа, а адрес, хранящийся в ссылке, является прямым адресом объекта.
Оба этих метода доступа к объектам имеют свои преимущества. Самым большим преимуществом использования дескрипторов для доступа является то, что то, что хранится в ссылке,"стабильность"Адрес дескриптора изменяет только указатель данных экземпляра в дескрипторе при перемещении объекта, и"Сама ссылка не нуждается в изменении". Самым большим преимуществом использования прямого доступа к указателю является то, что"высокоскоростной", что экономит время на позиционирование указателя.
вывоз мусора
Куча Java — это основная область, управляемая сборщиком мусора, поэтому она также называется"Куча мусора".С точки зрения сборки мусора, поскольку сборщик в основном использует алгоритм сборки мусора поколений, куча Java также может быть подразделена на: новое поколение и старое поколение: более подробно: пространство Eden, From Survivor, To Survivor и т. д. . . ."Целью дальнейшего деления является более эффективное использование памяти или ее более быстрое выделение."
Предметы предпочтительно размещаются в районе Эдема
В настоящее время все основные сборщики мусора используют алгоритм сборки по поколениям, поэтому необходимо разделить память кучи на новое поколение и старое поколение, чтобы мы могли выбрать подходящий алгоритм сборки мусора в соответствии с характеристиками каждого поколения.
В большинстве случаев объекты выделяются в райской зоне молодого поколения. Когда в области eden недостаточно места для выделения, виртуальная машина инициирует второстепенный сборщик мусора. Давайте проведем фактический тест ниже.
Перед тестированием давайте посмотрим"В чем разница между Minor GC и Full GC?"
- "ГК нового поколения (минор ГК)": Относится к действию по сборке мусора нового поколения. Незначительные сборщики мусора происходят очень часто, а скорость восстановления обычно выше.
- "GC пожилого возраста (Major GC/Full GC)": Относится к GC, возникающему в пожилом возрасте.Большой GC часто сопровождается по крайней мере одним второстепенным GC (не абсолютным), а скорость Главного GC обычно более чем в 10 раз ниже, чем у Малого GC.
Крупные предметы уходят прямо в старость
Большие объекты — это объекты, требующие большого объема непрерывной памяти (например, строки, массивы).
** Почему должно быть так? **Во избежание снижения эффективности из-за копирования, вызванного механизмом гарантии выделения памяти при выделении памяти для больших объектов.
Долгоживущие объекты вступают в старость
Если объект все еще жив после рождения Эдема и после первого Малого GC и может быть размещен Выжившим, он будет перемещен в ячейку Выжившего, а возраст объекта будет установлен на 1. Каждый раз, когда объект переживает MinorGC в Survivor, возраст увеличивается на 1 год, и когда его возраст увеличивается до определенного уровня (по умолчанию 15 лет), он будет переведен в старое поколение. Порог возраста для перевода объекта в старое поколение, который можно передать через параметр-XX:MaxTenuringThreshold
устанавливать.
Как узнать, мертв ли объект
подсчет ссылок
Добавить к объекту счетчик ссылок. Всякий раз, когда есть ссылка на него, счетчик увеличивается на 1; когда ссылка недействительна, счетчик уменьшается на 1; в любой момент объект, счетчик которого равен 0, больше не может быть использовал.
"Этот метод прост в реализации и эффективен, но текущая основная виртуальная машина не выбирает этот алгоритм для управления памятью, основная причина в том, что сложно решить проблему взаимных циклических ссылок между объектами."Так называемая проблема взаимной ссылки между объектами показана в следующем коде: За исключением того, что объекты objA и objB ссылаются друг на друга, между этими двумя объектами нет никакой ссылки. Но поскольку они ссылаются друг на друга, их счетчики ссылок не равны 0, поэтому алгоритм подсчета ссылок не может уведомить сборщик мусора о необходимости их повторного использования.
public class ReferenceCountingGc {
Object instance = null;
public static void main(String[] args) {
ReferenceCountingGc objA = new ReferenceCountingGc();
ReferenceCountingGc objB = new ReferenceCountingGc();
objA.instance = objB; // 循环引用
objB.instance = objA; // 循环引用
objA = null;
objB = null;
}
}
Анализ доступности
Основная идея этого алгоритма состоит в том, чтобы пройти серию""Корни ГК""Объект GC Roots используется в качестве отправной точки, и поиск начинается с этих узлов.Путь, который проходит узел, называется цепочкой ссылок.Когда объект не имеет никакой цепочки ссылок, связанной с GC Roots, это доказывает, что объект недоступен.
Что может быть корнем GC Roots
- Объект, применяемый в стеке виртуальной машины (область локальных переменных в кадре стека, также называемая таблицей локальных переменных).
- Объекты, на которые ссылаются статические свойства класса в области метода
- Объект, на который ссылается константа в области метода
- Объекты, на которые ссылается JNI (собственные методы) в стеке собственных методов
Давайте поговорим о цитатах здесь
Цитаты Большой четверки
"1. Сильная ссылка"
Большинство цитат, которые мы использовали ранее, на самом деле были сильными цитатами, которые используются чаще всего. Если объект имеет сильную ссылку, то что-то вроде"предметы первой необходимости", сборщик мусора никогда не будет его перерабатывать. Когда места в памяти недостаточно, виртуальная машина Java скорее выдаст ошибку OutOfMemoryError, вызывающую аварийное завершение программы, чем решит проблему нехватки памяти путем произвольного повторного использования объектов с надежными ссылками.
"2. Мягкая ссылка"
Если объект имеет только мягкие ссылки, то что-то вроде"Незаменимые предметы первой необходимости". Если памяти достаточно, сборщик мусора не будет ее освобождать, если памяти недостаточно, память этих объектов будет освобождена. Объект может использоваться программой до тех пор, пока он не будет собран сборщиком мусора. Мягкие ссылки могут использоваться для реализации кэшей, чувствительных к памяти.
Мягкие ссылки можно использовать в сочетании с очередью ссылок (ReferenceQueue).Если объект, на который ссылается мягкая ссылка, является сборщиком мусора, виртуальная машина JAVA добавит мягкую ссылку в соответствующую очередь ссылок.
"3. Слабая ссылка (WeakReference)"
Если объект имеет только слабые ссылки, то что-то вроде"Незаменимые предметы первой необходимости". Разница между слабыми ссылками и мягкими ссылками заключается в том, что объекты только со слабыми ссылками имеют более короткое время жизни. В процессе сканирования области памяти, находящейся под юрисдикцией потока сборщика мусора, как только будет найден объект только со слабыми ссылками, его память будет освобождена независимо от того, достаточно ли текущего места в памяти или нет. Однако, поскольку сборщик мусора является потоком с низким приоритетом, объекты, имеющие только слабые ссылки, не могут быть быстро обнаружены.
Слабые ссылки можно использовать в сочетании с очередью ссылок (ReferenceQueue).Если объект, на который ссылается слабая ссылка, является сборщиком мусора, виртуальная машина Java добавит слабую ссылку в соответствующую очередь ссылок.
"4. PhantomReference"
«Виртуальная ссылка», как следует из названия, существует только по названию, в отличие от других ссылок, виртуальная ссылка не определяет жизненный цикл объекта. Если объект содержит только фантомные ссылки, он может быть удален сборщиком мусора в любое время, как если бы у него вообще не было ссылок.
"Виртуальные ссылки в основном используются для отслеживания активности объектов, собирающих мусор.".
"Одно различие между фантомными ссылками и мягкими и слабыми ссылками заключается в том, что:"Виртуальная ссылка должна использоваться вместе с очередью ссылок (ReferenceQueue). Когда сборщик мусора готов освободить объект, если он обнаружит, что у него все еще есть виртуальная ссылка, он добавит виртуальную ссылку в связанную с ним очередь ссылок перед освобождением памяти объекта. Программа может узнать, будет ли объект, на который делается ссылка, сборщиком мусора, определив, добавлена ли виртуальная ссылка в очередь ссылок. Если программа обнаруживает, что в очередь ссылок добавлена виртуальная ссылка, она может предпринять необходимые действия, прежде чем память объекта, на который указывает ссылка, будет освобождена.
Недостижимые объекты не "должны умереть"
Даже недостижимые в методе анализа достижимости объекты не являются «обязательными к смерти». В настоящее время они временно находятся в «стадии испытания». Чтобы действительно объявить объект мертвым, требуется как минимум два процесса маркировки; в методе анализа пола маркируется и фильтруется впервые, а условием фильтрации является необходимость выполнения метода finalize для этого объекта. Если объект не переопределяет метод finalize или метод finalize был вызван виртуальной машиной, виртуальная машина считает эти два случая излишними.
Объекты, которые определены для выполнения, будут помещены в очередь на повторную отметку, если только объект не связан с каким-либо объектом в цепочке ссылок, иначе он будет действительно переработан.
Как определить, является ли константа устаревшей константой
Пул констант времени выполнения в основном повторно использует отброшенные константы. Итак, как мы можем судить, что константа является устаревшей константой?
Если строка "abc" существует в пуле констант, если ни один объект String в настоящее время не ссылается на строковую константу, это означает, что константа "abc" является заброшенной константой. Если восстановление памяти происходит в это время и это необходимо, "abc " Пул констант будет очищен системой.
Как понять, что урок бесполезен
Определить, является ли константа «устаревшей константой», относительно просто, но гораздо сложнее определить, является ли класс «бесполезным классом». Класс должен соответствовать следующим трем условиям одновременно, чтобы его можно было рассматривать."«Бесполезный класс»":
- Все экземпляры этого класса были утилизированы, то есть в куче Java нет экземпляров этого класса.
- ClassLoader, загружавший класс, был переработан.
- На объект java.lang.Class, соответствующий этому классу, нигде нет ссылок, и доступ к методам этого класса посредством отражения нигде невозможен.
Виртуальная машина может перерабатывать бесполезные классы, которые соответствуют трем вышеуказанным условиям.То, что мы говорим здесь, это только «может», а не объект, который будет переработан, если он не используется.
Алгоритм сборки мусора
алгоритм маркировки-развертки
Алгоритм разделен на этапы «маркировки» и «очистки»: сначала маркируются все объекты, которые необходимо переработать, а после завершения маркировки все отмеченные объекты равномерно перерабатываются. Это самый простой алгоритм сбора, и последующие алгоритмы получаются путем улучшения его недостатков. У этого алгоритма сборки мусора есть две очевидные проблемы:
- Вопросы эффективности
- Проблемы с пространством (много несмежных фрагментов после пометки «Очистить»)
алгоритм маркировки-сопоставления
Алгоритм маркировки, предложенный в соответствии с характеристиками старости, процесс маркировки по-прежнему такой же, как алгоритм «маркировать-очистить», но последующие шаги заключаются не в непосредственной переработке перерабатываемых объектов, а в перемещении всех уцелевших объектов в один конец, а затем непосредственно очистить память за пределами конечной границы.
алгоритм репликации
Для решения проблемы эффективности появился алгоритм сбора «копий». Он может делить память на два блока одинакового размера и использовать один из них одновременно. Когда память этого блока израсходована, уцелевшие объекты копируются в другой блок, а затем снова очищается использованное пространство. Таким образом, каждое освобождение памяти должно освободить половину диапазона памяти.
Алгоритм сбора поколений
"Например, в новом поколении в каждой коллекции будет умирать большое количество объектов, поэтому можно выбрать алгоритм репликации, и каждая сборка мусора может быть завершена с небольшими затратами на репликацию объекта. Вероятность выживания объектов в старости относительно высока, а лишнего места для его выделения нет, поэтому для сборки мусора мы должны выбрать алгоритм «пометить-очистить» или «пометить-очистить»."
уборщик мусора
- Серийный коллекционер
- Коллекционер ParNew
- Параллельный сборщик мусора
- Сборщик CMS
- коллектор G1
Серийный коллекционер
Последовательный сборщик Сборщик — самый простой и самый старый сборщик мусора. Как видно из названия, этот сборщик является однопоточным. это"«Одна нить»"Значение не только означает, что он будет использовать только один поток сборки мусора для завершения работы по сборке мусора, но, что более важно, он должен приостанавливать все остальные рабочие потоки, когда выполняется работа по сборке мусора (""Stop The World"") до конца его сбора.
"В новом поколении используется алгоритм репликации, а в старом поколении используется алгоритм маркировки-сопоставления."
Дизайнеры виртуальной машины наверняка знали о плохом пользовательском опыте, который приносил Stop The World, поэтому в последующих конструкциях сборщиков мусора время паузы становилось все короче и короче (паузы все еще есть, и процесс поиска лучшего сборщика мусора продолжается). .
Но лучше ли сборщик Serial других сборщиков мусора? Конечно есть, это"Простой и эффективный (по сравнению с однопоточными другими сборщиками)". Поскольку сборщик Serial не требует дополнительных затрат на взаимодействие потоков, он естественным образом может обеспечить высокую эффективность однопоточного сбора данных. Последовательный сборщик — хороший выбор для виртуальных машин, работающих в клиентском режиме.
Коллекционер ParNew
"Сборщик ParNew на самом деле является многопоточной версией сборщика Serial.За исключением использования многопоточности для сборки мусора, остальное поведение (параметры управления, алгоритмы сбора, стратегии утилизации и т. д.) точно такое же, как у Serial. коллекционер."
"В новом поколении используется алгоритм репликации, а в старом поколении используется алгоритм маркировки-сопоставления."
Это первый выбор для многих виртуальных машин, работающих в режиме сервера, за исключением последовательного сборщика, он работает только с сборщиком CMS (настоящим параллельным сборщиком, который будет представлен позже).
"Дополнение к концепциям параллельности и параллелизма:"
- "Параллельно": Относится к нескольким потокам сборки мусора, работающим параллельно, но пользовательский поток в это время все еще находится в состоянии ожидания.
- "Параллельно": Относится к одновременному выполнению пользовательского потока и потока сборки мусора (но не обязательно параллельно, может выполняться попеременно), пользовательская программа продолжает работать, а сборщик мусора работает на другом процессоре.
Параллельный сборщик мусора
Сборщик Parallel Scavenge также является многопоточным сборщиком, использующим алгоритм репликации, и выглядит почти так же, как ParNew.
"Сборщик Parallel Scavenge ориентирован на пропускную способность (эффективное использование ЦП). Сборщики мусора, такие как CMS, больше внимания уделяют времени паузы пользовательских потоков (улучшая взаимодействие с пользователем). Так называемая пропускная способность — это отношение времени, затраченного ЦП на выполнение пользовательского кода, к общему времени, затраченному на ЦП."Сборщик Parallel Scavenge предоставляет пользователям множество параметров, позволяющих найти наиболее подходящее время паузы или максимальную пропускную способность.Если вы мало знаете о работе сборщика и если ручная оптимизация затруднена, вы можете передать оптимизацию управления памятью. к виртуальной машине Хороший выбор.
"В новом поколении используется алгоритм репликации, а в старом поколении используется алгоритм маркировки-сопоставления."
Серийный старый коллекционер
"Версия серийного коллектора старого поколения", который также является однопоточным сборщиком. У него две основные цели: одна предназначена для использования с сборщиком Parallel Scavenge в JDK1.5 и более ранних версиях, а другая — в качестве запасного варианта для сборщика CMS.
Параллельный старый коллектор
"Старая версия сборщика Parallel Scavenge.". Используйте многопоточность и алгоритм «отметить и отсортировать». Там, где важны пропускная способность и ресурсы ЦП, сборщику Parallel Scavenge и сборщику Parallel Old можно отдать приоритет.
Сборщик CMS
"Сборщик CMS (Concurrent Mark Sweep) — это сборщик, целью которого является получение кратчайшего времени паузы сбора. Он очень подходит для использования в приложениях, ориентированных на взаимодействие с пользователем."
"Сборщик CMS (Concurrent Mark Sweep) — это первый настоящий параллельный сборщик виртуальной машины HotSpot, и впервые поток сборки мусора и пользовательский поток работают (в основном) одновременно."
от имени"Mark Sweep"Как видно из этих двух слов, сборщик CMS — это"Алгоритм маркировки-развертки"По сравнению с предыдущими сборщиками мусора процесс его работы более сложен. Весь процесс делится на четыре этапа:
- "Начальная разметка:"Приостановить все другие потоки и записать объекты, напрямую связанные с корнем, что очень быстро;
- "Параллельная маркировка:"Одновременно открывайте GC и пользовательские потоки и используйте структуру замыкания для записи доступных объектов. Но в конце этой фазы структура замыкания не обязательно будет содержать все достижимые в данный момент объекты. Поскольку пользовательский поток может постоянно обновлять поле ссылки, поток GC не может гарантировать производительность анализа достижимости в реальном времени. Таким образом, этот алгоритм будет отслеживать, где происходят эти эталонные обновления.
- "Переименовать:"Целью фазы перемаркировки является исправление записей маркировки той части объектов, маркировка которых изменена, поскольку программа пользователя продолжает работать во время параллельной маркировки.Время паузы на этой фазе обычно немного больше, чем при начальной маркировке. фаза, которая намного длиннее, чем фаза одновременной маркировки.
- "Параллельная очистка:"Запускается пользовательский поток, и поток GC начинает очищать отмеченную область.
Из названия видно, что это отличный сборщик мусора, основные преимущества:"Параллельный сбор, низкая пауза". Но у него есть следующие три очевидных недостатка:
- "Чувствителен к ресурсам ЦП;"
- "Не справляется с плавающим мусором;"
- "Алгоритм повторного использования, который он использует — алгоритм «пометки и очистки» приводит к большой фрагментации пространства в конце коллекции."
коллектор G1
"G1 (Garbage-First) — серверно-ориентированный сборщик мусора, в основном для машин с несколькими процессорами и большим объемом памяти, с высокой вероятностью удовлетворяющий требованиям времени паузы сборщика мусора, но обладающий также высокими характеристиками производительности."
Считается важной эволюционной функцией виртуальной машины HotSpot в JDK1.7. Он имеет следующие характеристики:
- "Параллелизм и параллелизм": G1 может в полной мере использовать аппаратные преимущества ЦП и многоядерной среды, а также использовать несколько ЦП (ЦП или ядро ЦП), чтобы сократить время паузы Stop-The-World. Некоторым другим сборщикам изначально необходимо приостановить действие GC, выполняемое потоком Java, но сборщик G1 все же может позволить программе Java продолжать выполнение параллельным образом.
- "Коллекция поколений": хотя G1 может самостоятельно управлять всей кучей GC без сотрудничества с другими сборщиками, он все же сохраняет концепцию генерации.
- "пространственная интеграция": В отличие от алгоритма "отметить-очистить" CMS, G1 является сборщиком, основанным на алгоритме "отметить-очистить" в целом, с локальной точки зрения он основан на алгоритме "копирования".
- "предсказуемая пауза": это еще одно большое преимущество G1 по сравнению с CMS. Сокращение времени паузы является общей задачей G1 и CMS, но в дополнение к достижению низкой паузы, G1 также может установить предсказуемую модель времени паузы, позволяя пользователям четко указывать временной интервал. длиной M миллисекунд.
Работа коллектора G1 условно делится на следующие этапы:
- "начальная отметка"
- "одновременная маркировка"
- "окончательная оценка"
- "Проверка на переработку"
"Сборщик G1 поддерживает список приоритетов в фоновом режиме.Каждый раз, в соответствии с разрешенным временем сбора, предпочтительно выбирается регион с наибольшим значением восстановления (отсюда и его название Garbage-First).". Такое использование Region для разделения пространства памяти и метода утилизации приоритетных областей гарантирует, что сборщик GF сможет собрать максимально эффективную информацию за ограниченное время (память будет разделена на ноль).
Как выбрать сборщик мусора
-
Один ЦП или небольшая память, автономная память
-XX:+UseSerialGC
-
Несколько ЦП, требующих максимальной пропускной способности, например приложения для фоновых вычислений.
-XX:+UseParallelGC -XX:+UseParallelOldGC
-
Несколько процессоров, стремление к малому времени паузы, быстрый отклик, например, интернет-приложения
-XX:+ParNewGC -XX:+UseConcMarkSweepGC
параметр | Сборщик мусора молодого поколения | алгоритм нового поколения | Сборщик мусора старого поколения | алгоритм старости |
---|---|---|---|---|
UseSerialGC | SerialGC | копировать | SerialOldGC | стандартизировать |
UseParNewGC | ParNew | копировать | SerialOldGC | стандартизировать |
UseParallelGC UseParallelOldGC |
Parallel[Scavenge] | копировать | Parallel Old | стандартизировать |
UseConcMarkSweepGC | ParNew | копировать | Комбинация коллектора CMS+Serial Old (Serial Old в качестве резервного коллектора для ошибок CMS) | SD |
UseG1GC | G1 принимает стандартное целое | Частично путем копирования алгоритма |
Параметры настройки JVM
❝Здесь представлены только некоторые часто используемые, и есть дополнительные пояснения...
❞
-Xms128m -Xmx4096m -Xss1024K -XX:MetaspaceSize=512m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseSerialGC
- -Xms: начальный размер памяти, по умолчанию 1/64 физической памяти, что эквивалентно -XX:InitialHeapSize
- -Xmx: максимальная выделенная память, физическая память по умолчанию 1/4, эквивалентно -XX:MaxHeapSize
- -Xss: Установить размер стека одного потока, по умолчанию 542K~1024K, что эквивалентно -XX:ThreadStackSize
- -Xmn: установить размер молодого поколения
- -XX:MetaspaceSize: установить размер метапространства.
- -XX:+PrintGCDetails: вывод подробной информации журнала сбора мусора, например [имя: использование памяти до сборки мусора -> использование памяти после сборки мусора (общий объем памяти в этой области)]
- -XX:SurvivorRatio: Установите соотношение пространства Eden и S0/S1 в новом поколении, по умолчанию -XX:SurvivorRatio=8,Eden:S0:S1=8:1:1
- -XX:NewRatio: установить соотношение молодого поколения и старого поколения в структуре кучи, например: по умолчанию -XX:NewRatio=2 Новое поколение равно 1, старое поколение равно 2, молодое поколение составляет 1/ 3 всей кучи, а значение NewRatio несколько предложений.Поэзия задает пропорцию старого поколения, а оставшийся 1 - для нового поколения
- -XX:MaxTenuringThreshold: Установить максимальный возраст мусора, по умолчанию -XX:MaxTenuringThreshold=15
- -XX:+UseSerialGC:Последовательный сборщик мусора
- -XX:+UseParallelGC: Параллельный сборщик мусора
❝Это не легко создать, если вы найдете это полезным, дайте маленькую звезду.гитхаб-адрес😁😁😁
❞
В этой статье используетсяmdniceнабор текста