Делает ли установка объектов Java на ноль больше? - PullRequest
108 голосов
/ 12 мая 2009

Я просматривал старые книги и нашел копию "Практической Явы" Питера Хаггера. В разделе производительности рекомендуется установить ссылки на объекты на null, когда они больше не нужны.

В Java установка ссылок на объекты на null повышает производительность или эффективность сборки мусора? Если да, то в каких случаях это проблема? Контейнерные классы? Состав объекта? Анонимные внутренние классы?

Я вижу это в коде довольно часто. Это устаревший совет по программированию или он все еще полезен?

Ответы [ 6 ]

69 голосов
/ 12 мая 2009

Это немного зависит от того, когда вы думали об обнулении ссылки.

Если у вас есть цепочка объектов A-> B-> C, то, когда A недостижима, A, B и C будут иметь право на сборку мусора (при условии, что больше ничего не относится ни к B, ни к C). Например, нет нужды и никогда не было необходимости явно устанавливать ссылки A-> B или B-> C на ноль.

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

В случае, когда раньше было , некоторые советы по установке ссылок на null были конкретно в длинной области , когда объект, интенсивно использующий память, перестал использоваться на полпути через область действия . Например:

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;             <-- explicitly set to null
  doSomethingElse();
}

Обоснование здесь заключалось в том, что, поскольку obj все еще находится в области видимости, то без явного обнуления ссылки он не станет сборщиком мусора до тех пор, пока метод doSomethingElse () не завершится , И это совет, который , вероятно, больше не действует в современных JVM : оказывается, что JIT-компилятор может определить, в какой момент данная локальная ссылка на объект больше не используется.

25 голосов
/ 12 мая 2009

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

См. «Эффективное Java, 2-е изд», пункт 6: «Устранить ссылки на устаревшие объекты».

10 голосов
/ 12 мая 2009

Поля экземпляра, элементы массива

Если есть ссылка на объект, его нельзя собрать мусором. Особенно, если этот объект (и весь граф за ним) большой, есть только одна ссылка, которая останавливает сборку мусора, и эта ссылка больше не нужна, это прискорбная ситуация.

Патологические случаи - это объект, который сохраняет неестественный экземпляр всего дерева DOM XML, которое использовалось для его настройки, MBean, который не был незарегистрирован, или единственную ссылку на объект из неразвернутого веб-приложения, которая предотвращает загрузчик всего класса. от выгрузки.

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

Переменные области действия:

Если вы планируете установить для локальной переменной значение null до конца ее области видимости, чтобы ее можно было использовать сборщиком мусора и пометить ее как «непригодную для использования с этого момента», вам следует рассмотреть возможность ее установки более вместо этого ограниченная область.

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;          //   <-- explicitly set to null
  doSomethingElse();
}

становится

{
  {  
     BigObject obj = ...
     doSomethingWith(obj);
  }    //         <-- obj goes out of scope
  doSomethingElse();
}

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

5 голосов
/ 12 мая 2009

В средах с ограничением памяти (например, в мобильных телефонах) это может быть полезно. При установке значения null объект не должен ждать, пока переменная выйдет из области видимости, чтобы быть gc'd.

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

1 голос
/ 26 апреля 2017

Во-первых, это ничего не значит, что вы устанавливаете объект на null. Я объясняю это ниже:

List list1 = new ArrayList();
List list2 = list1;

В приведенном выше фрагменте кода мы создаем имя переменной ссылки на объект list1 из ArrayList объекта, который сохраняется в памяти. Таким образом, list1 ссылается на этот объект, и это не более чем переменная. И во второй строке кода мы копируем ссылку с list1 на list2. Теперь вернемся к вашему вопросу, если я сделаю:

list1 = null;

это означает, что list1 больше не ссылается на какой-либо объект, который хранится в памяти, поэтому list2 также будет не на что ссылаться. Так что если вы проверите размер list2:

list2.size(); //it gives you 0

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

Надеюсь, это прояснит концепцию.

0 голосов
/ 11 января 2018

Одной из причин для этого является устранение устаревших ссылок на объекты. Вы можете прочитать текст здесь.

...