Как обучение JVM проходило от начала до отказа?

Java JVM алгоритм Java EE

предисловие

Только лысина может стать сильнее

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

Цель изучения JVM также очень проста:

  • Быть в состоянии узнать, что такое JVM, что она делает для нас и как она это делает. Уметь понимать некоторые вещи, которые вы не понимали, когда были новичком
  • Обсудить во время интервью
  • в состоянии заставить

(Источник изображения:zhuanlan.zhihu.com/p/25511795, вторгнуться и удалить)

Отказ от ответственности: полный текст по умолчанию относится к виртуальной машине HotSpot.

1. Кратко о JVM

1.1 Давайте рассмотрим простую программу на Java.

Теперь у меня есть JavaBean:


public class Java3y {

    // 姓名
    private String name;

    // 年龄
    private int age;

   	//.....各种get/set方法/toString
}

Тестовый класс:


public class Java3yTest {

    public static void main(String[] args) {
        
        Java3y java3y = new Java3y();
        java3y.setName("Java3y");
        System.out.println(java3y);

    }
}

Мы, должно быть, использовали его в началеjavacСкомпилировать.javaкод файла, используемыйjavaкоманда для выполнения скомпилированного.classдокумент.

Исходные файлы Java:

При использовании IDE для запуска по щелчку на самом деле это две командыкомбинироватьВстанем (скомпилируем и запустим), что нам удобно для разработки.

Создать файл класса

Разберите файл класса, чтобы получить результат

1.2 Процесс компиляции

.javaФайл создается компилятором исходного кода Java (упомянутым вышеjavac.exe) для завершения блок-схема выглядит следующим образом:

Исходный код Java компилируется следующимтриСостав процесса:

  • Анализ и ввод в таблицу символов
  • Обработка аннотаций
  • Семантический анализ и генерация файлов классов

1.2.1 Время компиляции — синтаксический сахар

Синтаксический сахар можно рассматривать какНекоторые «хитрости», реализованные компилятором, эти "трюки" могут сделатьЭффективность "большое улучшение".

Самое примечательное, чтоДженерикиТеперь об этом синтаксическом сахаре можно сказать, что мы его часто используем!

  • Дженерики существуют только в исходном коде Java,После компиляцииБудет заменен исходным необработанным типом (Raw Type, также известным как голый тип). Этот процесс также известен как:Общее стирание.

С синтаксическим сахаром дженериков:

  • Код стал более лаконичным [без принудительного преобразования]
  • Программа более надежна [пока нет предупреждения во время компиляции, во время выполнения не будет ClassCastException]
  • Читабельность и стабильность [При написании коллекции тип ограничен]

Узнайте больше о дженериках:

1.3 JVM реализует кроссплатформенность

До сих пор мы прошлиjavac.exeКомпилятор компилирует наш.javaСгенерированный файл исходного кода.classфайл!

Эти.classФайл явноне может работать напрямуюДа, это не похоже на язык C (exe-файлы генерируются после компиляции cpp и запускаются напрямую)

Эти.classфайл отправленуправляется JVM!

  • JVM работает в операционной системе, и инструкции каждой операционной системы различны, иJDK различает операционные системы, если в вашей локальной системе установлен JDK, JDK совместим с текущей системой.
  • Байт-код класса работает на JVM, поэтомуНеважно, в какой операционной системе был скомпилирован байт-код класса., если он соответствует спецификации JVM, файл с байт-кодом можно запускать.
  • Таким образом, Java является кроссплатформенной ---> скомпилируйте один раз, запускайте везде!

1.4 Недовольство между class-файлом и JVM

1.4.1 Время загрузки класса

Теперь два сгенерированных в нашем примере.classдокументБудет ли он загружаться непосредственно в JVM?? ?

Спецификация виртуальной машины строго оговаривает, что есть только 5 ситуаций, которые должны быть"инициализировать" класс немедленно(файл класса загружен в JVM):

  • Создайте экземпляр класса (по-новому). Получите доступ к статической переменной класса или интерфейса или присвойте значение статической переменной и вызовите статический метод класса
  • способ отражения
  • Инициализировать подкласс класса, родительский класс будет инициализирован
  • Класс, помеченный как класс запуска при запуске виртуальной машины Java, напрямую использует команду java.exe для запуска основного класса (класса, содержащего основной метод).
  • При использовании динамической языковой поддержки JDK1.7(....)

так:

  • Загрузка классов Java является динамической. Она не загружает все классы одновременно, а затем запускает их, а гарантирует, что основные классы (например, базовые классы), которые запускают программу, полностью загружены в jvm. Что касается других классов,загружать только при необходимости. Это конечно дляЭкономия памяти.

1.4.2 Как загрузить классы в jvm

файл класса череззагрузчик классовЗагрузился в JVM!

JavaПо умолчанию есть три загрузчика классов:

Должностные обязанности индивидуальных грузчиков:

  • 1) Bootstrap ClassLoader: отвечает за загрузку jre/lib/ в $JAVA_HOMErt.jarВсе классы в нем реализованы на C++, а не на подклассах ClassLoader.
  • 2) Extension ClassLoader: отвечает за загрузку платформы javaрасширенияНекоторые пакеты jar, включая jre/lib/*.jar в $JAVA_HOME или пакеты jar в каталоге, указанном параметром -Djava.ext.dirs.
  • 3) App ClassLoader: отвечает за записьclasspathПакет Jar и указанный класс каталога

процесс работы:

  • 1. Когда AppClassLoader загружает класс, он не будет пытаться сначала загрузить класс сам по себе, а делегирует запрос на загрузку класса родительскому загрузчику классов ExtClassLoader для завершения.
  • 2. Когда ExtClassLoader загружает класс, он не будет пытаться сначала загрузить класс сам по себе, а делегирует запрос на загрузку класса BootStrapClassLoader для завершения.
  • 3. Если BootStrapClassLoader не загружается (например, класс не найден в $JAVA_HOME/jre/lib), для попытки загрузки будет использоваться ExtClassLoader;
  • 4. Если ExtClassLoader также не загружается, для загрузки будет использоваться AppClassLoader.
  • 5. Если AppClassLoader также не загружается, будет сообщено об исключении ClassNotFoundException.

На самом деле это так называемаяМодель родительского делегирования. Проще говоря: если загрузчик класса получает запрос на загрузку класса, он не будет пытаться сначала загрузить сам класс, аЗапрос делегируется родительскому загрузчику для завершения, в свою очередь.

выгода:

  • Предотвращение появления в памяти нескольких копий одного и того же байт-кода(угол безопасности)

Специальное примечание:

  • После того, как загрузчик классов успешно загрузит класс, онjava.lang.ClassЭкземпляры класса кэшируются. В следующий раз, когда класс будет запрошен для загрузки, загрузчик класса будет напрямую использовать кэшированный экземпляр класса, ибольше не буду пытаться загрузить.

1.4.2 Подробный процесс загрузки класса

Загрузчик загружается в jvm, а потом собственно снова делитсянесколько шагов:

  • Загрузите, найдите и загрузите двоичные данные класса, также в куче JavaСоздайте объект класса java.lang.Class.
  • Подключение, подключение включает в себя три части: проверка, подготовка, инициализация.
    • 1) проверка, формат файла, метаданные, байт-код, проверка ссылки на символ;
    • 2) Подготовить, выделить память для статических переменных класса и инициализировать их значениями по умолчанию;
    • 3) Разобрать, преобразовать символическую ссылку в классе в прямую ссылку
  • Инициализируйте, присвойте правильное начальное значение статическим переменным класса.

1.4.3 Мгновенный редактор JIT

Как правило, мы можем подумать: после того, как JVM загрузит эти файлы классов, для этих байт-кодовВынимайте по одному, выполняйте по одному-->Разбор парсера.

Но если так, тослишком медленно!

Наша JVM реализована так:

  • заключается в том, чтобы поместить эти байт-коды JavaПерекомпилировать и оптимизировать, сгенерируйте машинный код и позвольте центральному процессору выполнить его напрямую. Это сделает код более эффективным.
  • Компиляция тоже требует времени, мы обычногорячий кодкомпилировать,Прямой парсинг негорячего кодаДостаточно.

Объяснение кода точки доступа: 1. Метод, который вызывается несколько раз. Во-вторых, тело цикла выполняется несколько раз.

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

  • выборка
  • прилавок

В настоящее время HotSpot используетпуть счетчика, который подготавливает два типа счетчиков для каждого метода:

  • Счетчик вызовов метода (счетчик вызовов)
  • Назад EdgeCounter.
  • При условии определения рабочих параметров виртуальной машины эти два счетчика имеют определенный порог,Когда счетчик переполняется за пороговое значение, запускается JIT-компиляция..

1.4.4 Назад к примеру

Следите за нашей программой, нашимJava3yTest.classФайл загружается в JVM загрузчиком AppClassLoader (поскольку ни ExtClassLoader, ни загрузчик BootStrap не загружают его [родительская модель делегирования]).

Потом я узнал, что мы хотим использовать класс Java3y, нашJava3y.classФайл загружается в JVM загрузчиком AppClassLoader (поскольку ни ExtClassLoader, ни загрузчик BootStrap не будут его загружать [родительская модель делегирования])

Для получения подробной информации см.:

Дальнейшее чтение:

1.5 Что делает JVM после загрузки класса?

После прохождения проверки загрузки класса следующая виртуальная машинавыделит память для новых объектов.

1.5.1 Модель памяти JVM

Во-первых, давайте взглянем на модель памяти JVM:

  • Модель памяти JVM нарисованная на базе jdk1.8 ---> провожу сравнениетонкий.

Краткий взгляд на модель памяти, краткий взгляд на то, что каждая область хранит (что она делает):

  • куча:хранить экземпляр объекта, почти все экземпляры объекта выделяют здесь память
  • Стек виртуальных машин: стек виртуальных машин описываетМодель памяти выполнения метода Java: метод создается одновременно с выполнением каждого методакадр стека(Stack Frame) используется для хранения такой информации, как таблица локальных переменных, стек операций, динамическая ссылка, выход из метода и т. д.
  • Стек собственных методов: стек собственных методов используется виртуальной машиной.Служба собственных методов.
  • Область метода: СохраненоСведения о метаданных класса, загружаемые виртуальной машиной(метапространство)
  • Счетчик программ: выполнение байт-кода текущим потоком.индикатор номера строки

1.5.2 Поток в примере

я прихожуКраткое описание макросовВот рабочий процесс в нашем примере:

  • 1. Пройтиjava.exeбегатьJava3yTest.class, который затем загружается в JVM,Metaspace хранит информацию о классе(включая имя класса, информацию о методе, информацию о поле...).
  • 2. Затем JVM находит запись основной функции (main) Java3yTest, создает кадр стека для основной функции и начинает выполнение основной функции.
  • 3. Первая команда основной функцииJava3y java3y = new Java3y();Это позволяет JVM создать объект Java3y, но в настоящее время в области методов нет информации о классе Java3y, поэтому JVM немедленно загружает класс Java3y и помещает информацию о типе класса Java3y в область методов (метапространство).
  • 4. После загрузки класса Java3y первое, что делает виртуальная машина Java, — это выделяет память для нового экземпляра Java3y в области кучи, а затем вызывает конструктор для инициализации экземпляра Java3y.Экземпляр Java3y содержит информацию о типе, указывающую на класс Java3y в области методов.(которая содержит ссылку на таблицу методов, базовую реализацию динамической привязки Java)
  • 5. При использованииjava3y.setName("Java3y");Когда JVMНайти объект Java3y на основе ссылки java3y, а затем найдите информацию о типе класса Java3y в области методов в соответствии со ссылкой, содержащейся в объекте Java3y.Методический лист,получитьsetName()адрес байт-кода функции
  • 6. ДляsetName()Функция создает кадр стека и начинает работатьsetName()функция

На самом деле много чего сделано с микроуровня, как было сказано вышепроцесс загрузки класса(загрузить-->подключить (проверить, подготовить, разобрать)-->инициализировать), после загрузки класса jvmвыделить для него память(Также много чего делаю при выделении памяти). Так как эти шаги не пошаговые, будет много процессов "хаотичной начальной загрузки", поэтому их сложно описать четко.

Использованная литература:

1.6 Кратко о различных пулах констант

Когда я писал эту статью, я думал, что был прав.String s = "aaa";Подобные проблемы больше не являются проблемой, пока я не столкнулсяString.intern()такой методString s1 = new String("1") + new String("2");при смешивании вместе

  • Я обнаружил, что был еще слишком молод.

Прежде всего, я впервые прочитал эту статью технической команды Meituan:Специальности.Meituan.com/in_depth_UN…---Углубленный анализ String#intern

Ну, тогда я был ошеломлен. Приведу его пример:


public static void main(String[] args) {
    String s = new String("1");
    s.intern();
    String s2 = "1";
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    s3.intern();
    String s4 = "11";
    System.out.println(s3 == s4);
}

Результат печати такой

  • jdk7,8 под ложным истинным

После смены положения:


public static void main(String[] args) {

    String s = new String("1");
    String s2 = "1";
    s.intern();
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    String s4 = "11";
    s3.intern();
    System.out.println(s3 == s4);
}

Результат печати:

  • jdk7,8 под ложным ложным

В статье есть очень подробный анализ, но я все еще в замешательстве, прочитав ее несколько раз. Итак, я знаю, что в моих знаниях еще есть лазейки, и тогда я читал статьи, написанные R University ранее:

После просмотра я еще больше запутался.

Позже я увидел такой ответ на жиху:

  • Ууху. Call.com/question/55…--- Когда «литерал» в новой строке («литерал») в Java входит в пул строковых констант?

В сочетании с онлайн-информацией и моими собственными размышлениями, давайте разберемся с пониманием постоянного пула~~

1.6.1 Ситуация с каждым постоянным пулом

Для после jdk1.7:

  • Постоянный бассейн находится вв куче
  • Пул констант времени выполнения расположен по адресув куче
  • Пул строковых констант находится по адресув куче

Постоянный пул хранит:

  • Литерал: Текстовые строки и т. д. ----> Здесь будут вводиться строковые литералы, заключенные в двойные кавычки.
  • Символические ссылки
    • Полное квалифицированное имя классов и интерфейсов
    • Имя поля и дескриптор (Descriptor)
    • имя и дескриптор метода

Таблица постоянного пула, используемая для хранения различных литералов и символических ссылок, сгенерированных во время компиляции, эта часть будет вПосле того, как класс загружен, он сохраняется в рабочем времени области метода.---> Источник: Углубленное понимание расширенных функций и рекомендаций JVM виртуальной машины Java (второе издание)

Теперь наш пул констант времени выполнения только что изменил свое местоположение (исходная область методов, теперь в куче), но ясно, что:После загрузки класса данные в пуле констант будут храниться в пуле констант времени выполнения.!

В HotSpot VM глобальная таблица, в которую записываются интернированные строки, называется StringTable, которая по сути является HashSet. УведомлениеОн хранит только ссылку на экземпляр java.lang.String, а не на содержимое объекта String.

Пул строковых констант хранит только ссылки, а не содержимое!

Давайте еще раз взглянем на наш внутренний метод:


 * When the intern method is invoked, if the pool already contains a
 * string equal to this {@code String} object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this {@code String} object is added to the
 * pool and a reference to this {@code String} object is returned.
 
  • Если текущая строка существует в пуле констант, то напрямую вернуть ее ссылку в пуле констант.
  • Если такой строки в пуле констант нет, ссылка на строку будет сохранена в пуле констант, а затем ссылка на строку будет возвращена напрямую!

1.6.2 Анализ темы

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


public static void main(String[] args) {

 
    String s = new String("1");

    s.intern();


    String s2 = "1";

    System.out.println(s == s2);// false
    System.out.println("-----------关注公众号:Java3y-------------");
}

первое предложение:String s = new String("1");

Второе предложение:s.intern();Обнаружено, что строковый объект «1» уже существует в пуле строковых констант, непосредственноВозвращает ссылку на кучу в пуле строковых констант (но не полученную)--> В это время ссылка s по-прежнему указывает на объект в куче

Третье предложение:String s2 = "1";найти пул строковых константСсылка на объект сохраненаТеперь напрямую верните ссылку на пул строковых констант на строку в куче.

легко увидеть,Две ссылки не совпадают! так верни ложь.



    public static void main(String[] args) {

        System.out.println("-----------关注公众号:Java3y-------------");

        String s3 = new String("1") + new String("1");


        s3.intern();


        String s4 = "11";
        System.out.println(s3 == s4); // true
    }

первое предложение:String s3 = new String("1") + new String("1");Примечание. В настоящее время объект «11» не содержит ссылку в пуле строковых констант.

Второе предложение:s3.intern();Найден объект "11"не находится в пуле строковых констант, поэтому поместите объект "11" в пул строковых константСохранить ссылку на текущую строкувозвращениессылка на текущую строку (но не полученную)

Третье предложение:String s4 = "11";Обнаружил, что уже есть ссылка на пул строковых констант, вернитесь напрямую (Он также получает ссылку на ту же точку, что и s3.)

В соответствии с вышеизложенным: в конце концов вернет true~~~

Если вы все еще не уверены в студентах, вы можете попробовать их принять.intern()Возвращаемое значение метода, а затем посмотрите на вышеуказанную картинку, оно должно быть понятно.


Следующее зависит от вас, посмотрите, освоили ли вы это:


    public static void main(String[] args) {

        String s = new String("1");
        String s2 = "1";
        s.intern();
        System.out.println(s == s2);//false

        String s3 = new String("1") + new String("1");
        String s4 = "11";
        s3.intern();
        System.out.println(s3 == s4);//false
    }

и:


    public static void main(String[] args) {
        String s1 = new String("he") + new String("llo");
        String s2 = new String("h") + new String("ello");
        String s3 = s1.intern();
        String s4 = s2.intern();
        System.out.println(s1 == s3);// true
        System.out.println(s1 == s4);// true
    }

1.7GC сборка мусора

Можно сказать, что сборка мусора GC — это очень важная часть знаний о JVM, и ее следует объяснить очень подробно. Но пока я учусь, я нашел хорошие статьи, объясняющие сборку мусора.

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

1.7.1 Краткое введение в сборку мусора JVM

В C++ мы знаем, что созданный объект нужно удалить вручную. Наша Java-программа работает в JVM, и JVM может помочь нам «автоматически» утилизировать ненужные объекты, что очень удобно для нас.

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

Во-первых, что перерабатывает JVMМусор, мусор в нашей программе больше не нужен. Прежде чем сборщик мусора соберет кучу, первое, что он делает, — это определяет, какие из этих объектов все еще «живы».которые "умерли". Есть два распространенных способа определить, какие объекты «мертвые»:

  • Метод подсчета ссылок --> Проблема такого рода, которую трудно решить циклической ссылкой между объектами.
  • Алгоритмы анализа достижимости--> Основная JVM использует этот метод

Теперь есть возможность определить, какие объекты "мертвые". Теперь нам нужно утилизировать эти "мертвые" объекты. Существует несколько алгоритмов утилизации:

  • алгоритм маркировки-развертки
  • алгоритм репликации
  • алгоритм маркировки-сопоставления
  • Алгоритм сбора поколений

(Подробнее об этих алгоритмах см. в вопросах интервью ниже)~

Будь то алгоритм анализа достижимости или алгоритм сборки мусора, JVM используетточный GC. JVM использует наборOopMapСтруктура данных для хранения всех ссылок на объекты (так что вам не нужно просматривать всю память, чтобы найти место за временем). И не будет генерировать OopMap для всех инструкций, только вБезопасная точкаРодился ООПМАП в г.безопасный районЗапустите GC на .

  • С помощью OopMap HotSpot можетбыстро и точноПолное перечисление корней GC (анализ достижимости).

Алгоритм сборки мусора, описанный выше, можно рассматривать только какМетодология, реализация посадки естьуборщик мусора:

  • Серийный коллекционер
  • Коллекционер ParNew
  • Параллельный сборщик мусора
  • Серийный Старый коллекционер
  • Параллельный Старый коллектор
  • Сборщик CMS
  • коллектор G1

Большинство вышеперечисленных сборщиков могут общаться друг с другомиспользовать в сочетаниииз

1.8 Параметры и настройка JVM

Многие студенты, выполнявшие проект JavaWeb (SSH/SSM), могли столкнуться с такими ошибками, как OutofMemory. Тоже очень удобно решать.При запуске добавить параметр.

Выше также многое сказано о JVM ---> разделении памяти JVM, различных сборщиках мусора JVM.

Размер выделения памяти, какой сборщик использовать, это может быть определено нами.В соответствии с потребностями, фактическая ситуация, чтобы указатьДа, я не буду вдаваться в подробности, просто вернусь, чтобы заполнить яму, когда она действительно будет использована~~~~~

Использованная литература:

2. Вопросы для интервью с JVM

Возьмите несколько общих вопросов интервью JVM, чтобы ответить,Углубите понимание и заполните пробелы:

  • 1. Подробная модель памяти jvm
  • 2. Расскажите об обстоятельствах, при которых происходит переполнение или утечка памяти?
  • 3. Расскажите о стеке потоков Java
  • 4. Каковы условия оценки процесса продвижения от молодого поколения к старому поколению JVM?
  • 5. JVM часто имеет полную сборку мусора, как я могу решить проблему онлайн?
  • 6. Почему при загрузке класса используется режим родительского делегирования и есть ли какие-либо сценарии, нарушающие этот режим?
  • 7. Порядок создания классов
  • 8. Механизм сборки мусора JVM, когда запускать MinorGC и другие операции
  • 9. Что такое полный процесс GC (от ygc до fgc) в JVM
  • 10. Различные ресайклеры, каждый со своими преимуществами и недостатками, ориентируясь на CMS, G1
  • 11. Различные алгоритмы утилизации
  • 12. Ошибка OOM, ошибка переполнения стека, ошибка пространства permgen

Источник темы:

2.1 Подробная модель памяти jvm

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

конкретныйможет бытьДавайте поговорим о PermGen (постоянная генерация) до jdk1.7, замените его на Metaspace (метапространство)

  • Данные, изначально хранящиеся в постоянном поколении: символические ссылки (символы) передаются в нативную кучу; литералы (интернированные строки) передаются в кучу java; статические переменные класса (статика класса) передаются в кучу java.
  • Метапространство (metaspace) хранит информацию о метаданных класса (метаданные)
  • Суть метапространства аналогична сущности перманентного поколения, какРеализация области метода в спецификации JVM. Но самая большая разница между метапространством и постоянной генерацией заключается в следующем:Метапространство находится не в виртуальной машине, а использует локальную память.
  • Преимущества замены: 1. Строка существует в постоянном поколении, которое подвержено проблемам с производительностью и переполнению памяти. 2. Постоянная генерация внесет лишнюю сложность в GC, а эффективность рециркуляции будет низкой.

Источник изображения:blog.CSDN.net/top hawk/art…

Использованная литература:

2.2 При каких обстоятельствах происходит переполнение или утечка памяти?

Причина утечки памяти проста:

  • объект доступен(всегда цитируется)
  • но объектне будет использоваться

Распространенные примеры утечек памяти:


 public static void main(String[] args) {

        Set set = new HashSet();

        for (int i = 0; i < 10; i++) {
            Object object = new Object();
            set.add(object);

            // 设置为空,这对象我不再用了
            object = null;
        }

        // 但是set集合中还维护这obj的引用,gc不会回收object对象
        System.out.println(set);
    }

Решить эту проблему с утечкой памяти также очень просто, установите значение null, этого можно избежать.обращатьсяПроблема с утечкой памяти. Другие утечки памяти анализируются поэтапно.

Ссылки на утечку памяти:

Причина переполнения памяти:

  • Утечка памяти приводит к тому, что память стека продолжает расти, вызывая переполнение памяти.
  • Большое количество банок, файлы классов загружаются, места для загрузки классов не хватает, переполнение
  • Работа с большим количеством объектов приводит к тому, что пространство кучи переполняется.
  • Nio напрямую управляет памятью, а память слишком велика, чтобы вызвать переполнение.

решать:

  • Проверьте программу на утечку памяти
  • Установите параметры для увеличения пространства
  • Есть ли в коде бесконечный цикл или цикл создает слишком много повторяющихся объектов,
  • Проверьте, используется ли nio для прямого управления памятью.

Использованная литература:

2.3 Поговорим о стеке потоков

Стек потока здесь должен относиться к стеку виртуальной машины...

Спецификация JVM позволяетна Java-потоквладеть своим собственнымОтдельный стек JVM, который является стеком вызовов метода Java.

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

Пока поток работает,Активен только один кадр стека, называемый «текущий кадр активного стека», текущий кадр активного стека всегда является стеком виртуальной машины.верхний элемент стека.

пройти черезjstackИнструмент для просмотра статуса потока

Использованная литература:

2.4 Каковы условия оценки процесса продвижения от молодого поколения к старому поколению JVM?

  1. Некоторые объекты будут скопированы и скопированы в области From и To,Поменяйтесь так 15 раз(Определяется параметром JVM MaxTenuringThreshold, который по умолчанию равен 15), и если он все же выживет, то будет храниться в старом возрасте.
  2. еслиОбъекты, размер которых превышает половину Эдема, будут размещены непосредственно в старом, если старый не может быть аллоцирован, будет выполняться majorGC, если меньше половины eden, но места не хватает, то будет выполнен minorGC, то есть GC нового поколения.
  3. После незначительного gc, если выживший все еще не может быть усыплен, поместите его в старость.
  4. Динамическое суждение о возрасте, объекты старше или равные определенному возрасту превышают половину оставшегося пространства, а объекты старше или равные определенному возрасту напрямую входят в старость

2.5 JVM часто имеет полный сборщик мусора, как устранить проблему онлайн

Этот вопрос основан на условиях срабатывания полного GC:

  • Если есть perm gen (jdk1.8 ушел),Выделить место для perm gen, но места не хватает, вызовет полный сбор мусора.
    • Поэтому посмотрите, не слишком ли мало значение perm gen area.
  • System.gc()вызов метода
    • Это вообще никем не называется~~~
  • когдастатистикаСредний размер Minor GC продвигается к старому поколениюБольше, чем оставшееся пространство старого поколения, это вызовет полную сборку мусора (это видно с разных сторон)
    • Да или нетЧасто создаются большие объекты (также возможно, что область eden установлена ​​слишком маленькой)(Большие объекты непосредственно выделяются в старом возрасте, что приводит к нехватке места в старом возрасте ---> таким образом, частый gc)
    • Да или нетКосмическая установка старости слишком мала(Несколько объектов в Minor GC больше, чем оставшееся пространство в старости)

2.6 Почему при загрузке классов используется родительская модель делегирования и есть ли какие-либо сценарии, нарушающие эту модель?

Важным применением модели родительского делегирования является решение проблемы загрузки классов.проблемы с безопасностью.

  • Предположим, разработчик написалjava.lang.Objectкласс, чтобы обмануть JVM. Теперь он хочет использовать обычайClassLoaderзагрузить свой собственныйjava.lang.Objectсвоего рода.
  • Однако, к счастью, модель родительского делегирования не позволила ему добиться успеха. Поскольку JVM будет отдавать приоритетBootstrap ClassLoaderвстречается на путиjava.lang.Objectкласс и загрузить его

Обязательно ли загрузка классов Java соответствует родительской модели делегирования?

Использованная литература:

2.7 Порядок создания классов

  • 1. Статические члены родительского класса и статические блоки инициализации выполняются в том порядке, в котором они появляются в коде.
  • 2. Статические элементы подкласса и статические блоки инициализации, выполняемые в том порядке, в котором они появляются в коде.
  • 3. Члены экземпляра родительского класса и блоки инициализации экземпляра выполняются в том порядке, в котором они появляются в коде.
  • 4. Конструктор родительского класса
  • 5. Члены экземпляра подкласса и блоки инициализации экземпляра, выполняемые в том порядке, в котором они появляются в коде.
  • 6. Конструктор подкласса

Проверьте, действительно ли вы понимаете:


class Dervied extends Base {


    private String name = "Java3y";

    public Dervied() {
        tellName();
        printName();
    }

    public void tellName() {
        System.out.println("Dervied tell name: " + name);
    }

    public void printName() {
        System.out.println("Dervied print name: " + name);
    }

    public static void main(String[] args) {

        new Dervied();
    }
}

class Base {

    private String name = "公众号";

    public Base() {
        tellName();
        printName();
    }

    public void tellName() {
        System.out.println("Base tell name: " + name);
    }

    public void printName() {
        System.out.println("Base print name: " + name);
    }
}

Выходные данные:


Dervied tell name: null
Dervied print name: null
Dervied tell name: Java3y
Dervied print name: Java3y

Однокласснику, который ошибся в первый раз, нравится, а подписку добавить не так уж и много (хахаха

2.8 Механизм сборки мусора JVM, когда запускать MinorGC и другие операции

MinorGC срабатывает, когда область eden в молодом поколении заполнена (когда в новом поколении не хватает места).

2.9 Что такое полный процесс GC (от ygc до fgc) в JVM

Этот вопрос не очень ясен (ограниченный уровень... Если вы знаете значение этого вопроса, вы можете оставить сообщение в области комментариев~~)

  • Потому что, насколько я понимаю: выполнение fgc не приведет к выполнению ygc~~

Что такое YGC и FGC

  • ЮГК:gc куча молодого поколения. Частота относительно высока, потому что большинство объектов имеют короткую продолжительность жизни и собираются в молодом поколении. Стоимость исполнения небольшая.
  • ФСК:gc для всей кучи. Когда использование пространства кучи по умолчанию достигает 80% (настраивается), будет запущен fgc. Взяв в качестве примера нашу производственную среду, fgc срабатывает редко, иногда раз в 10 дней или в неделю.

Когда выполнять YGC и FGC

  • a.Места в Эдеме недостаточно, запустите молодой gc
  • b.старого места недостаточно, постоянного места недостаточно, вызовите методSystem.gc(), пессимистическая стратегия в ygc, когда выгружается оперативная информация о памяти (jmap –dump:live), будет выполняться полный gc

2.10 Различные алгоритмы утилизации

Существует три основных алгоритма GC:

  • алгоритм маркировки-развертки
  • алгоритм репликации
  • алгоритм сжатия тегов
  • Наши обычно используемые сборщики мусора обычно используютАлгоритм сбора поколений(На самом деле это комбинация вышеперечисленных алгоритмов, и в разных регионах используются разные алгоритмы).

конкретный:

  • Алгоритм маркировки-развертки, алгоритм «Марк-развертка» (Mark-Sweep), как следует из его названия, алгоритм делится на «маркировку» и «развертку» в два этапа: сначала помечают все объекты, которые необходимо переработать, после завершения маркировки Собирают все отмеченные объекты равномерно.
  • Алгоритм копирования, алгоритм сбора «копирования», делит доступную память на два блока одинакового размера в соответствии с их емкостью и использует только один из них за раз. Когда память этого блока израсходована, уцелевшие объекты копируются в другой блок, а затем однократно очищается использованное пространство памяти.
  • Алгоритм маркировки-сжатия, процесс маркировки такой же, как и алгоритм «маркировка-очистка», но последующие шаги заключаются не в непосредственной очистке перерабатываемых объектов, а в перемещении всех уцелевших объектов в один конец, а затем непосредственной очистке. память за пределами конечной границы
  • Алгоритм сбора поколений, алгоритм «Коллекции поколений», делит кучу Java на новое поколение и старое поколение, чтобы можно было выбрать наиболее подходящий алгоритм сбора в соответствии с характеристиками каждого поколения.

2.11 Различные ресайклеры, их преимущества и недостатки, ориентир на CMS, G1

Изображение взято из «Глубокого понимания виртуальной машины Java: расширенные специальные эффекты JVM и лучшая реализация», изображениеМежду двумя коллекторами есть провод, указывающий на то, что их можно использовать вместе..

  • Серийный коллекционер, серийный коллекционер самый старый,Самый стабильный и эффективный коллектор, но может производитьдолгая пауза, используя только один поток для повторного использования.
  • Коллектор ParNew, коллектор ParNew на самом деле является последовательным коллекторомМногопоточная версия.
  • Параллельный сборщик, сборщик Parallel Scavenge похож на сборщик ParNew, параллельный сборщикУделите больше внимания пропускной способности системы.
  • Сборщик Parallel Old, Parallel Old — это более старая версия сборщика Parallel Scavenge, использующая многопоточный алгоритм «маркировка-сортировка».
  • Сборщик CMS, сборщик CMS (Concurrent Mark Sweep) являетсяПолучите минимальное время паузы на переработкусборщик целей. это нужноПотреблять дополнительные ресурсы ЦП и памяти, когда ресурсы ЦП и памяти ограничены, а ЦП меньше, это увеличивает нагрузку на систему. CMSНе справляется с плавающим мусором. Алгоритм маркировки и очистки CMS, который приводит к большому количествуСоздание космического мусора.
  • Сборщик G1, G1 (Garbage-First) — сборщик мусора, ориентированный на сервер, в основном для машин, оснащенных несколькими процессорами и памятью большого объема.Соответствуя требованиям времени паузы GC с очень высокой вероятностью, он также имеет характеристики производительности с высокой пропускной способностью..

2.12 ошибка переполнения стека, ошибка пространства permgen

В основном появляется ошибка stackoverflow:

  • В стеке виртуальной машины (глубина стека, запрошенная потоком, больше максимальной глубины, разрешенной блокировкой стека виртуальной машины)

ошибка пространства permgen (для jdk версии 1.7 до):

  • Множество файлов классов
  • Постоянное переполнение пула памяти

3. Резюме

В целом, JVM является более теоретической на начальном уровне, и можно получить более глубокий опыт, выполняя определенные действия. этоГлавное попасть.~

Эта статья ленивая и ленивая, и считается разобранной в более важных знаниях о JVM, о SpringCloud планирую узнать и написать позже.

Использованная литература:

Если в статье есть какие-либо ошибки, пожалуйста, поправьте меня, и мы сможем общаться друг с другом. Учащиеся, привыкшие читать технические статьи в WeChat и желающие получить больше ресурсов по Java, могутОбратите внимание на публичный аккаунт WeChat: Java3y.

Оглавление Навигация по статьям: