Сборка мусора Java - Что это делает? - PullRequest
3 голосов
/ 14 октября 2011

Мой учитель Java (курс средней школы) говорил о циклах, и она сказала, что если у вас есть цикл for, например:

for (int i = 0; i < max; i++) {
    //something
}

, вы не можете использовать переменную i внецикл, потому что функция сбора мусора удаляет его, потому что он чувствует, что он "ненужен" (я знаю о областях и что это BS, потому что то же самое происходит во всех языках, а в C ++ даже нет сборки мусора).Теперь вопрос в том ... Что делает сборщик мусора?(Я посмотрел его, и это имело какое-то отношение к кучам, о которых я пока не знаю, поэтому кто-то объяснил мне это)

Спасибо

Ответы [ 2 ]

7 голосов
/ 14 октября 2011

(я знаю об областях и о том, что это BS, потому что то же самое происходит во всех языках, а в C ++ даже нет сборки мусора).

Правильно. Переменная i не может использоваться вне цикла из-за области действия - она ​​не имеет ничего , связанной с GC (вне потенциальной способности достижения объекта).

Теперь вопрос в том ... Что на самом деле делает сборщик мусора? (Я посмотрел его, и это имело какое-то отношение к кучам, о которых я пока не знаю, поэтому кто-то объяснил мне это)

Сборщик мусора отвечает за восстановление объектов , которые больше не сильно достижимы . Сборщик мусора не имеет ничего [прямого отношения] к переменным, хотя переменная может поддерживать объект в высокой степени достижимым. (Кроме того, примитивные значения, такие как int не являются объектами , поэтому GC никогда не обрабатывает их; -)

Я бы рекомендовал прочитать главу 9 «Внутри виртуальной машины Java»: Сборка мусора и Правда о сборке мусора , так как я считаю, что они предоставят достаточные ответы / понимание и обоснование. (Сборник мусора запись в википедии также является хорошим началом и хорошо обобщает GC в целом.)

Из "Правды":

Объект переходит в недоступное состояние, когда нет более сильных ссылок на него [является не сильно достижимым]. Когда объект недоступен, он является кандидатом на сбор. . Обратите внимание на формулировку: если объект является кандидатом на сбор, это не означает, что он будет немедленно собран. JVM может свободно откладывать сбор данных до тех пор, пока не возникнет непосредственная потребность в памяти, используемой объектом.

Удачного кодирования.

4 голосов
/ 14 октября 2011

Пример вашего учителя не очень хорош, потому что i, вероятно, хранится в стеке, так как это примитив.Лучшим примером будет:

public String helloWorld() {
    StringBuilder builder = new StringBuilder();
    builder.append("Hello");
    builder.append(" ");
    builder.append("World!");
    return builder.toString();
}

В первой строке функции мы выделяем новый объект (new StringBuilder()).Это выделяет некоторую память в куче , которая впоследствии должна быть освобождена.В C ++ вы бы сделали delete builder в конце, чтобы обработать это (или выделить его в стеке - но вы не можете сделать это в Java, поэтому я думаю, что это разумный пример).

Сборка мусора - это альтернативный метод, в котором ничего не происходит с builder в конце функции.Вместо этого периодически запускается процесс, называемый сборщиком мусора, который проверяет, какие объекты используются или не используются, и избавляется от всего, что не является.В примере, который я привел, сборщик мусора запустится, заметит, что больше нет способа получить доступ к builder и удалить его.

Сборщик мусора по умолчанию в Java выполняет то, что называется «пометить и очистить», где он в основномпросматривает все переменные, к которым имеет доступ, и отмечает их (установлен некоторый флаг).Затем он удаляет все, что не помечено.

Я думаю, что на еще более низком уровне он фактически перемещает все доступное в новую область памяти и удаляет все в старой области памяти (потому что все еще тамне был доступен).

Более простой метод сбора мусора называется «подсчет ссылок», где все, что динамически размещается, имеет счетчик ссылок - сообщая программе, сколько переменных указано в этом месте памяти.Если счетчик ссылок когда-либо достигнет 0, никто не использует эту память, и она может быть немедленно освобождена.В прошлый раз, когда я проверял, стандартный интерпретатор Python (CPython) использует это.

Проблема с подсчетом ссылок заключается в том, что вы можете получить циклы:

class Node {
    Node next;
}

public void breakReferenceCountingAlgorithm() {
    Node a = new Node();
    Node b = new Node();
    a.next = b;
    b.next = a;
}

В конце этой функциии b оба ссылаются один раз (друг на друга), но они не доступны.Ява поймает это и мусор собирает их так или иначе.Python не будет.


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

for(int i = 0; i < 100; i++) {
    System.out.println("stuff");
}

// This i is a different variable
for(int i = 0; i < 100; i++) {
    System.out.println("more stuff");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...