Может быть, немного поздно, но текущее объяснение совершенно неудовлетворительно для меня, и я думаю, что у меня есть более разумное объяснение.
Прежде всего каждый java GC выполняет какую-то трассировку из корневого наборатак или иначе.Это означает, что если старая голова будет собрана, мы все равно не будем читать переменную next
- нет причин делать это.Следовательно, IF head собирается на следующей итерации, это не имеет значения.
IF в приведенном выше предложении является важной частью здесь.Разница между установкой рядом с чем-то другим не имеет значения для сбора самой головы, но может иметь значение для других объектов.
Давайте предположим, что простой GC поколения: если голова находится в молодом наборе, этовсе равно собрали в следующем ГК.Но если он в старом наборе, он будет собран только тогда, когда мы сделаем полный сбор данных, что случается редко.
Так что же произойдет, если голова будет в старом сете, и мы проведем молодую сборную?В этом случае JVM предполагает, что каждый объект в старой куче все еще жив, и добавляет все ссылки от старых до молодых объектов в корневой набор для молодого GC.И это именно то, чего здесь избегает назначение: запись в старую кучу обычно защищена барьером записи или чем-то таким, что JVM может перехватывать такие назначения и обрабатывать их корректно - в нашем случае это удаляет объект next
, указанный накорневой набор, который имеет последствия.
Краткий пример:
Предположим, у нас есть 1 (old) -> 2 (young) -> 3 (xx)
.Если мы удалим 1 и 2 сейчас из нашего списка, мы можем ожидать, что оба элемента будут собраны следующим GC.Но если возникает только молодой GC, и мы НЕ удалили указатель next
в старых, оба элемента 1 и 2 не будут собраны.В противоположность этому, если мы удалили указатель в 1, 2 будет собираться молодым ГК ..