JVM определяет, что объект мертв, а практика проверяет восстановление сборщика мусора.

Введение

提升自身价值有多重要?

После взлетов и падений я видел мужчин и женщин. Со временем не будет вечных изменений!

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

Вы можете не понимать в определенном возрасте, но если вы однажды не будете так заняты, вам придется подумать о своем собственном пути и своих следах. Посмотрите, чего вы хотите. Если это все, что вам нужно, почему вы выглядите несчастным?

это хорошо! Давай, иди навстречу тому, кем хочешь быть!

2. Вопросы для собеседования

谢飞机,小记!Пообедав в полдень, я начал оцепеневать. Почему я не могу выучить эти знания? Это не приходит мне в голову!

Се Цзифэй : Здравствуйте, брат-интервьюер, я хочу задать вопрос.

Интервьюер : Что?

Се Цзифэй : Это знание не проникает в мозг!

Интервьюер : Это ...

Се Цзе : Я просто забыл посмотреть это, и забыл посмотреть!

Интервьюер : А практики нет? Сразу после прочтения подумал, а вот собрав, пойму? Никуда не углубляйтесь! ?

Се Цзифэй : Кажется, да! Там в любом случае?

Интервьюер : Хорошего пути нет, учеба - занятие скучное. Чтобы сократить потери времени на фрагментацию, было бы лучше использовать его для систематического обучения. Даже если вы пишете блог и записываете его, неплохо это проверить.

В-третьих, сначала проверьте сборку мусора

说是垃圾回收,我不引用了它就回收了?什么时候回收的?咋回收的?

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

Тестовый код

public class ReferenceCountingGC {

    public Object instance = null;
    private static final int _1MB = 1024 * 1024;
    /**
     * 这个成员属性的唯一意义就是占点内存, 以便能在GC日志中看清楚是否有回收过
     */
    private byte[] bigSize = new byte[2 * _1MB];

    public static void main(String[] args) {
        testGC();
    }

    public static void testGC() {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;
        objA = null;
        objB = null;
        // 假设在这行发生GC, objA和objB是否能被回收?
        System.gc();
    }

}

Этот пример взят из главы, посвященной алгоритмам подсчета ссылок, в «Углубленном понимании виртуальной машины Java».

Результатом этого примера является то, будут ли два объекта, для которых установлено значение null при взаимной ссылке, будут переработаны сборщиком мусора. Если вы просто посмотрите на алгоритм счетчика ссылок, то идентификаторы счетчика этих двух объектов не будут равны 0 и не могут быть переработаны. Но было ли это переработано?

Здесь мы сначала используем команду инструмента jvm, jstat для мониторинга. Поскольку процесс мониторинга требует, чтобы я набирал код вручную, что отнимает много времени, мы спим перед вызовом testGC ()  Thread.sleep(55000);. После запуска кода выполните следующие инструкции.

E:\itstack\git\github.com\interview>jps -l
10656
88464
38372 org.itstack.interview.ReferenceCountingGC
26552 sun.tools.jps.Jps
110056 org.jetbrains.jps.cmdline.Launcher

E:\itstack\git\github.com\interview>jstat -gc 38372 2000
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   6561.4   175104.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0   1288.0 65536.0    0.0     175104.0     8.0     4864.0 3982.6 512.0  440.5       1    0.003   1      0.000    0.003
10752.0 10752.0  0.0    0.0   65536.0   437.3    175104.0    1125.5   4864.0 3982.6 512.0  440.5       1    0.003   1      0.012    0.015
10752.0 10752.0  0.0    0.0   65536.0   437.3    175104.0    1125.5   4864.0 3982.6 512.0  440.5       1    0.003   1      0.012    0.015
  • S0C, S1C, размер первой и второй зоны выживания
  • S0U, S1U, размер первой и второй выживших областей
  • ЕС, ЕС, размер и использование Эдемского сада
  • OC, OU, размер и использование в старости
  • MC, MU, размер и область применения метода
  • CCSC, CCSU, размер и использование пространства класса сжатия
  • YGC, YGCT, время сборки мусора молодого поколения и отнимает много времени
  • FGC, FGCT, количество и затраты времени на сборку мусора в старости
  • GCT, общее время сборки мусора

Примечание : чтобы наблюдать за тремя задними рядами S1U = 1288.0, GCT = 0.003описанными уже в сборке мусора.

Далее протестируем другим способом. В запущенной программе добавьте параметры печати ГХ и наблюдайте за результатами изменения ГХ.

-XX:+PrintGCDetails  打印每次gc的回收情况 程序运行结束后打印堆空间内存信息(包含内存溢出的情况)
-XX:+PrintHeapAtGC  打印每次gc前后的内存情况
-XX:+PrintGCTimeStamps 打印每次gc的间隔的时间戳 full gc为每次对新生代老年代以及整个空间做统一的回收 系统中应该尽量避免
-XX:+TraceClassLoading  打印类加载情况
-XX:+PrintClassHistogram 打印每个类的实例的内存占用情况
-Xloggc:/Users/xiaofuge/Desktop/logs/log.log  配合上面的使用将上面的日志打印到指定文件
-XX:HeapDumpOnOutOfMemoryError 发生内存溢出将堆信息转存起来 以便分析

На этот раз вы можете удалить сон и добавить следующие параметры  -XX:+PrintGCDetails:

Результаты теста

[GC (System.gc()) [PSYoungGen: 9346K->936K(76288K)] 9346K->944K(251392K), 0.0008518 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 936K->0K(76288K)] [ParOldGen: 8K->764K(175104K)] 944K->764K(251392K), [Metaspace: 3405K->3405K(1056768K)], 0.0040034 secs] [Times: user=0.08 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 76288K, used 1966K [0x000000076b500000, 0x0000000770a00000, 0x00000007c0000000)
  eden space 65536K, 3% used [0x000000076b500000,0x000000076b6eb9e0,0x000000076f500000)
  from space 10752K, 0% used [0x000000076f500000,0x000000076f500000,0x000000076ff80000)
  to   space 10752K, 0% used [0x000000076ff80000,0x000000076ff80000,0x0000000770a00000)
 ParOldGen       total 175104K, used 764K [0x00000006c1e00000, 0x00000006cc900000, 0x000000076b500000)
  object space 175104K, 0% used [0x00000006c1e00000,0x00000006c1ebf100,0x00000006cc900000)
 Metaspace       used 3449K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 376K, capacity 388K, committed 512K, reserved 1048576K
  • По результатам работы видно, что журнал восстановления памяти был восстановлен с помощью Full GC.
  • Также можно увидеть, что JVM не полагается на счетчик ссылок, чтобы определить, жив ли объект. В противном случае они не будут переработаны.

В этом примере давайте взглянем на структуру знаний о сборке мусора JVM!

В-четвертых, инфраструктура сбора мусора JVM

Сборка мусора (сокращенно GC), Lisp, впервые появившийся в Массачусетском технологическом институте в 1960 году, был первым языком, в котором начали использовать технологию динамического выделения памяти и сбора мусора.

Сбор мусора в основном , чтобы сделать три вещи: 哪些内存需要回收,, 什么时候回收как переработка.

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

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

Рисунок 27-1 Структура знаний сборщика мусора

Ссылка для загрузки исходного изображения: http://book.bugstack.cn/#s/6jJp2icA

1. Судя по тому, что объект мертв

1.1 Счетчик ссылок

  1. Добавьте счетчик ссылок для каждого объекта, чтобы подсчитать количество ссылок на объект.
  2. Когда объект имеет соответствующую операцию обновления ссылок, счетчик ссылок целевого объекта увеличивается или уменьшается.
  3. Если счетчик ссылок объекта равен 0, это означает, что объект мертв и может быть собран сборщиком мусора.

С точки зрения реализации, хотя метод счетчика ссылок (Reference Counting) занимает некоторое дополнительное пространство в памяти для подсчета, его схема реализации проста, а эффективность оценки высока.Это хороший алгоритм.

Есть также некоторые известные ссылки, такие как технология Microsoft COM (объектная модель компонентов), Flash Player с использованием ActionScript 3 и язык Python.

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

1.2 Метод анализа доступности

Подсистемы управления памятью основных языков, таких как Java и C #, используют алгоритм анализа достижимости, чтобы определить, жив ли объект.

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

Корни GC включают;

  1. Глобальные ссылки, ссылки на статические объекты и постоянные объекты в области метода
  2. Контекст выполнения, ссылка на локальный объект в кадре стека методов Java, ссылка на объект, обрабатывающий JNI
  3. Поток Java запущен и не остановлен

Две большие проблемы

  1. Ложная тревога: мертвый объект помечается как живой и не подлежит сборке мусора. На время занимайте больше памяти и меньше влияйте.
  2. Ложный отчет: указанный объект (используемый) не был помечен как активный и был удален сборщиком мусора. Тогда прямая причина - сбой JVM. (STW может гарантировать точность метода анализа доступности и избежать занижения информации)

2. Алгоритм сборки мусора

2.1 Алгоритм Mark-Sweep (метка-развертка)

Алгоритм метки-развертки (метка-развертка)

  • Отметьте свободную память, занимаемую мертвыми объектами без ссылок, и запишите их в свободный список.
  • Когда необходимо создать новый объект, модуль управления памятью будет искать свободную память в свободном списке и выделять ее для вновь созданного объекта.
  • Этот метод очистки на самом деле очень прост и эффективен, но также существует проблема в том, что фрагментация памяти слишком серьезна.
  • Объекты в куче виртуальной машины Java должны быть непрерывно распределены, поэтому в крайних случаях, даже если общая оставшаяся память достаточна, эффективность поиска непрерывного распределения памяти будет низкой или слишком серьезно для выделения памяти. Перезапустите Tom Cat!
  • Такие алгоритмы есть в CMS, время паузы GC невелико, но есть недоработки алгоритма.

2.2 Алгоритм маркировки-копирования (mark-copy)

Алгоритм маркировки-копирования (mark-copy)

  • Из рисунка видно, что после очистки мусора на этот раз объем непрерывной памяти велик.
  • Таким образом, область памяти делится на две части, поддерживаемые двумя указателями от и до соответственно, и только область памяти, на которую указывает указатель from, используется для выделения памяти.
  • Когда происходит сборка мусора, живые объекты копируются в область памяти, на которую указывает указатель to, и происходит обмен указателями from и to.
  • Его польза очевидна, то есть решить проблему фрагментации памяти. Но это также приносит другие проблемы, половина места в куче тратится впустую.

2.3 алгоритм mark-compact (mark-compact)

Алгоритм пометки-компактности (mark-compact)

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

3. Сборщик мусора

3,1 Кайнозой

  1. Серийный
    1. Алгоритм: алгоритм копирования-пометки
    2. Описание: Простая и эффективная одноядерная машина, коллектор нового поколения по умолчанию в клиентском режиме;
  2. Параллельный ParNew
    1. Алгоритм: алгоритм копирования-пометки
    2. Примечание. Параллельная версия потоков сборки мусора не дает заметных результатов в сценариях с одним ЦП. Обычно используется в JVM в режиме клиента
  3. Параллельный поиск
    1. Алгоритм: алгоритм копирования-пометки
    2. Описание: цель состоит в достижении контролируемой пропускной способности (пропускная способность = время выполнения кода пользователя / (время выполнения кода пользователя + время сборки мусора));

3.2 Старость

  1. Серийный Старый
    1. Алгоритм: алгоритм сжатия меток
    2. Описание: Универсальная, однопоточная версия. Используется вместе с Parallel Scavenge до версии 1.5; в качестве плана резервного копирования для CMS.
  2. Параллельно Старый
    1. Алгоритм: алгоритм сжатия меток
    2. Описание: Многопоточный параллельный сборщик мусора для замены Serial Old и Parallel Scavenge.
  3. CMS
    1. Алгоритм: алгоритм очистки меток
    2. Описание: Чувствительность к ресурсам процессора и длительной паузе. Алгоритм mark-sweep генерирует фрагменты памяти, которые можно объединять и сортировать по параметрам. В основном заменен на G1

3.3 G1

  1. Алгоритм: алгоритм сжатия меток
  2. Описание: Подходит для многоядерных машин с большой памятью, многопоточного параллельного выполнения GC, низкой паузы, высокой эффективности восстановления.

Пять, резюме

  • JVM обладает обширными знаниями об автоматическом управлении памятью, включая соответствующие знания деталей алгоритма реализации HotSpot, которые не были упомянуты в этой статье, в том числе: защищенные узлы, защищенные области, карточные таблицы, барьеры записи и т. Д. Каждый контент заслуживает глубокого изучения.
  • Если на собеседовании задаются не только вопросы, лучший способ - это попрактиковаться в проверке и изучении. В остальном такое знание похоже на фильм с менее чем 3 баллами, трудно запомнить его содержание.
  • Весь контент также является процессом изучения и систематизации брата Сяо Фу, и мы продолжим копать и делиться им в будущем. Заинтересованные друзья могут обсуждать и учиться вместе.

Шесть, рекомендация серии

рекомендация

отblog.csdn.net/yunchan2675/article/details/113340974
рекомендация