сборка мусора невидимых переменных - PullRequest
1 голос
/ 07 ноября 2011

У меня следующий код:

void method() {
   Object o1 = new Object();
   {
      Object o2 = new Object();
      System.out.println(o2);
   }
   // any long operation
}

будет ли объект o2 иметь право на сборку мусора при выполнении long operation?

Ответы [ 4 ]

2 голосов
/ 07 ноября 2011

JLS определение достижимости:

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

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


Однако на практике ни одна из существующих JVM не может сказать, что Объект становится недоступным во время вызова, и большинство JVM заметят это только тогда, когда ... или после ... o2 выходит из области видимости. И даже в этом случае выполнение GC не гарантирует удаление объекта.


Примечание: это не противоречит JLS, потому что тест «достижимый объект» действительно говорит вам, когда объект не будет собирать мусор, а не когда он будет. JLS осторожно указывает, что объект может быть завершен и сборка мусора в некоторый момент после того, как он становится недоступным, но что он также может никогда не быть завершен и сборщик мусора.

0 голосов
/ 16 декабря 2011

Нет.Даже если объект, на который ссылается o2, недоступен, он не будет собираться мусором.Он находится в состоянии между достижимым и недоступным, называемым «невидимым», поскольку ссылочная переменная o2 все еще находится в стеке.

Чтобы сделать объект собираемым мусором, назначьте o2 = null или поместите этот блок в другую функцию.

источник: Книга 2001 года о производительности Java

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

Вы должны понимать, что ваша переменная o2 и ОБЪЕКТ, обозначенный o2, отличаются.

Переменная o2 фактически является указателем (хотя Java предпочитает называть их «ссылками») и занимает 4 или 8 байтов в кадре автоматического стека.Это хранилище не является сборщиком мусора и удаляется только при выходе из процедуры (или, возможно, при выходе из скобок {} в зависимости от реализации компилятора).

Объект "обозначенный" (на который указывает) o2 по существу доступен для возможной сборки мусора, как только операция new Object() заканчивается, и наличие указателя на него в o2 - это все, что предотвращает,Если переменная o2 либо больше не существует в кадре стека , либо в ней хранится другое значение указателя , тогда объект может быть собран.

Так что в вашем конкретном случае ответ"может быть".Это зависит от того, как компилятор и JIT обрабатывают {}, наряду с несколькими «удачливыми» вопросами относительно того, будет ли повторно использован блок хранения {} (но не метод в целом), место хранения для o2для чего-то другого.

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

да, однако это будет зависеть от того, не оптимизирует ли JVM / JIT это, чтобы избежать лишних операций со стеком

, что сделало бы его

Object o1 = new Object();
Object o2 = new Object();
System.out.println(o2);
// any long operation

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

, это будет означать, что o2 будетостаются в «доступной» памяти в соответствии с GC, если она не была перезаписана другой переменной в другой области видимости

...