Сборка мусора (Местные ссылки)

1

У меня есть путаница о том, как GC работает в Java.

Ниже приведен фрагмент кода, который смущает меня:

private Data data = new Data();

void main() {

    for (int i = 0; i < 100 ; i++) {
       MyThread thread = new MyThread(data);
       thread.start();
    }

    System.gc();

    // Long running process

} 

class MyThread extends Thread {
    private Data dataReference;

    MyThread(Data data) {
        dataReference = data;
    }
}

В приведенном выше примере, если gc вызывается перед продолжением (//Длительный процесс)

  • будут ли локальные темы собираться мусором?

  • Или GC пометит их (локальные ссылки MyThread) как живые, поскольку он содержит ссылку на глобальные справочные данные?

Теги:
garbage-collection
jvm

5 ответов

5
Лучший ответ

Экземпляры MyThread могут быть собраны сборщиком мусора только после того, как они сделаны (т.е. их метод run выполнен). После завершения цикла for любые экземпляры MyThread которых run метод run могут быть подвергнуты сборке мусора (поскольку на них нет ссылок).

Тот факт, что MyThread экземпляр MyThread содержит ссылку на экземпляр Data, который не собирает мусор, не влияет на время, MyThread экземпляры MyThread становятся пригодными для сбора мусора.

  • 0
    Спасибо за ответ. Итак, вы говорите, что, когда потоки завершены с исполнением, он имеет право на сборщик мусора, независимо от ссылок, которые он содержит внутри. (Я прав ??)
  • 2
    @NKR да. Пока он работает, он не может быть собран мусором. После завершения работы применяются те же правила, что и для любых других ссылочных типов - только если существуют ссылки на экземпляр MyThread (например, если у вашего основного метода был List<MyThread> содержащий ссылки на все созданные MyThread ), он нельзя собрать мусор. Тот факт, что он содержит ссылку на экземпляр, который не может быть собран мусором, не имеет значения.
Показать ещё 2 комментария
2

Ваши экземпляры MyThread не будут иметь права на сборку мусора, пока они не закончат работу.

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

Достижимый объект - это любой объект, к которому можно получить доступ в любом потенциальном продолжающемся вычислении из любого живого потока. (JLS 12.6.1)

Кроме того, так как живая нить можно назвать Thread.currentThread(), поток Thread объект должен также быть доступен до тех пор, как нить жить... независимо от каких - либо других ссылок на него.

Однако, если ссылка на объект Thread становится недоступной до start() метода start(), он будет иметь право на сборку мусора. Если бы это было не так, создание и не запускание Thread было бы утечкой памяти!

1

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

Объект получает право на сборку мусора или сборщик мусора, если он недоступен никаким живым потокам или статическим ссылкам. Другими словами, вы можете сказать, что объект становится пригодным для сборки мусора, если все его ссылки равны нулю. Циклические зависимости не считаются ссылками, поэтому, если объект A имеет ссылку на объект B, а объект B имеет ссылку на объект A, и у них нет никакой другой активной ссылки, тогда оба объекта A и B будут иметь право на сборку мусора.

мусора коллекции в Java-

1

Нет грантополучателя, что gc будет выполнен после System.gc(); вызов. Вызов System.gc() просто ПРЕДЛАГАЕТ, что ВМ выполняет сборку мусора.

И thread не является целью для gc. Поток не будет очищен, пока не закончится работа.

Вообще говоря, объекты считаются живыми, если на них все еще ссылаются другие.

0

Вы никогда не должны звонить System.gc. Система позвонит вам, когда не хватит памяти.

В Java GC работает в системе под названием Mark and Sweep. Алгоритм работает так

  • Начните с набора корневых объектов (GC-корней) и набора всех выделенных объектов.
  • Отметьте эти корни
  • Отметьте каждый объект, достижимый из этих корней, рекурсивно посещая каждое поле этих объектов.
  • Когда каждый возможный объект помечен, пройдитесь по списку всех объектов. Если предмет не помечен, освободите его.

(Это упрощение, современная реализация работает примерно так, но гораздо сложнее).

Так что же такое корень GC? Любой объект, сохраненный в локальной переменной, все еще находящейся в области видимости, в статической переменной, в ссылке JNI и во всех потоках, которые в данный момент работают.

Так что нет, поток не будет очищен, пока он не завершится. Вот почему потоки так легко создают память leak- до тех пор, пока они работают, любой объект, на который они ссылаются, не может быть освобожден, потому что корень GC (поток) имеет ссылку на него.

Но отношения всегда уходят от корня к другим объектам. Если Foo содержит ссылку на Bar, Foo может быть удалена независимо от того, может ли быть Bar. Но если Foo не может быть удален, то и Бар не может.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню