Почему «невидимый» объект не собирается сразу? - PullRequest
4 голосов
/ 19 ноября 2011

Я только что прочитал эту статью: Правда о сборке мусора

В разделе "A.3.3 Невидимый" объясняется, как и когда объект попадает всостояние invisible.

В приведенном ниже коде объект, присвоенный переменной foo, станет invisible после выхода из блока try/catch и останется со строгой ссылкой до выхода из метода run (что никогда не произойдет,потому что цикл while работает вечно).

public void run() {
    try {
        Object foo = new Object();
        foo.doSomething();
    } catch (Exception e) {
        // whatever
    }
    while (true) { // do stuff } // loop forever
}

В этой статье говорится:

Однако эффективная реализация JVM вряд ли обнулит ссылку, когда она выходит из области видимости.

Почему это не эффективно?

Моя попытка объяснения заключается в следующем:

Скажем, стек для этого метода содержит четыре элемента, степерь невидимый объект находится внизу.
Если вы хотите мгновенно собрать объект, вам нужно будет извлечь и сохранить три элемента, вытолкнуть и выбросить четвертый элемент, а затем поместить три еще действительных элемента обратно в стек.
Если вы соберете невидимый объект после того, как поток управления покинет метод run, ВМ может просто вытолкнуть все четыре элемента и отбросить их.

Ответы [ 2 ]

3 голосов
/ 19 ноября 2011

Локальные переменные находятся не в стеке операндов, а в области локальных переменных в кадре активации, доступ к которым осуществляется в случае ссылок через байтовые коды aload и astore, а обнуление локальной переменной не требует какого-либо нажатияи высовывание.

Обнуление неэффективно, поскольку оно не нужно:

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

РЕДАКТИРОВАТЬ:

Некоторые комментарии к последнему утверждению.

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

0 голосов
/ 19 ноября 2011

Очень простой ответ: ч / б неэффективно.

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

...