Коротко о самом главном в сборке мусора.
⚠️ Важно: это только концептуальная иллюстрация. В реальных средах исполнения JVM возможно других все сложнее!
💡 Терминология:
🔹 Stop The World
В управляемых языках это "механизм" остановки ваших потоков, для того, чтобы GC мог почистить память от ненужных объектов.
🔹 GC_POLL()
Фунция (на самом деле кусочек ассемблера), которая встраивается в ваш код и останавливает его исполнение по требованию GC.
🔹 Safe points
Места в вашем коде, куда может встроиться функция GC_POLL()
Где Safe points и где может встроиться GC_POLL():
- На входе в функцию 
- В конце горячих циклов (много итераций) 
- На выходе из функции 
- После вашего new (аллокации памяти) - если тип ссылочный 
- После вызовов функций 
- На определённых точках в коде с долгими вычислениями 
- По желанию производителей компилятора... 
⚠️ Safe points расставляются компилятором, программист напрямую на это не влияет.
⚙️ Примерный порядок действий:
- Компилятор вставляет в Вашу программу функцию и флаг, они доступны из любой точки программы 
//Флаг остановки мира
volatile bool gc_stop_the_world = false;
inline void GC_POLL() {
    if (gc_stop_the_world) {
        //Функция прерывающая выполнение 
        //текущего потока кода, ваш код замирает
        SuspendCurrentThread(); 
    }
}
- Расставляет функцию GC_POLL() по вашему коду в безопасных точках (Safe Points) 
Ваша функция:
void Foo(int count)
{
	GC_POLL(); //Вы этого не писали
	//...Какой-то ваш код
	for(var i = 0; i < count; ++i)
	{
		//...Какой-то ваш код
		GC_POLL() //Вы этого не писали
	}
	GC_POLL(); //Вы этого не писали
}
⚠️ Важно: компилятор вставляет минимальный ассемблерный код, а не прям call функции GC_POLL(), вызов GC_POLL() - представлен для урощения.
- При старте вашей программы запускается поток Вашей программы и отдельный поток/и GC, например такая функция: 
//Функция самого GC (Сборщик мусора, он же Garbage Collector)
//Она работает параллельно с вашей программой
void GC_WORK()
{
    while(true)
    {
        //Проверяем надо ли чистить память
        if(NeedToClearMemory()) 
        { 
            //Выставляем флаг "остановки мира"
            gc_stop_the_world = true;
            //Ждем когда все нужные потоки остановятся
            WaitStopTheWorld();
            
            //Очистка памяти
            ClearMemory();
            //Сбрасываем флаг "остановки мира"
            gc_stop_the_world = false;
            //Запускаем потоки в работу
            RunTheWorld();
        }
        else
        {
            Sleep(1); //Например можно засыпать на 1 мс
        }
    }
}
Когда GC решает что памяти мало, он:
- Поднимает флаг gc_stop_the_world. 
- Потоки самостоятельно доходят до GC_POLL() и приостанавливаются. 
- GC ждет остановку всех нужных потоков 
- Чистит память 
- Cбрасывает флаг gc_stop_the_world. 
- Возобновляет работу Ваших потоков. 
⚠️ Ваш код сам может вызвать работу GC, если вы вызвали аллокацию (создали новый управляемый объект), а свободной памяти у менеджера памяти нет:
    var x = new byte[1000]; 
    // Этот код может сам заставить GC выполнить работу, 
    // потому-что на самом деле вызывается код аллокатора памяти 
    // и просит минимум 1000 байт
⚠️ Некоторые потоки могут быть неуправляемыми тогда GC пропускает их при проверке.
