Делает ли установка объектов Java на ноль больше?
Я просматривал некоторые старые книги и нашел копию "Практической Явы" Питера Хаггера. В разделе производительности рекомендуется установить ссылки на объекты null
когда больше не нужен.
В Java, установка ссылок на объекты null
улучшить производительность или эффективность сбора мусора? Если да, то в каких случаях это проблема? Контейнерные классы? Состав объекта? Анонимные внутренние классы?
Я вижу это в коде довольно часто. Это устаревший совет по программированию или он все еще полезен?
6 ответов
Это немного зависит от того, когда вы думаете об обнулении ссылки.
Если у вас есть цепочка объектов 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-компилятор может определить, в какой момент данная локальная ссылка на объект больше не используется.
Нет, это не устаревший совет. Висячие ссылки все еще являются проблемой, особенно если вы, например, реализуете расширяемый контейнер массива (ArrayList
или тому подобное) с использованием предварительно выделенного массива. Элементы, превышающие "логический" размер списка, должны быть обнулены, иначе они не будут освобождены.
См. Effective Java 2nd ed, Пункт 6: Устраните ссылки на устаревшие объекты.
Поля экземпляра, элементы массива
Если есть ссылка на объект, он не может быть собран мусором. Особенно, если этот объект (и весь граф за ним) большой, есть только одна ссылка, которая останавливает сборку мусора, и эта ссылка больше не нужна, это прискорбная ситуация.
Патологические случаи - это объект, который сохраняет необязательный экземпляр для всего дерева DOM XML, которое использовалось для его настройки, MBean, который не был незарегистрирован, или единственную ссылку на объект из неразвернутого веб-приложения, которая предотвращает выгрузку целого загрузчика классов,
Так что, если вы не уверены, что объект, содержащий саму ссылку, все равно будет собираться мусором (или даже тогда), вы должны обнулить все, что вам больше не нужно.
Переменные области:
Если вы рассматриваете возможность установки локальной переменной равной нулю до конца ее области видимости, чтобы ее мог утилизировать сборщик мусора и пометить ее как "непригодную для использования с этого момента", вы должны вместо этого поместить ее в более ограниченную область видимости.,
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; // <-- explicitly set to null
doSomethingElse();
}
становится
{
{
BigObject obj = ...
doSomethingWith(obj);
} // <-- obj goes out of scope
doSomethingElse();
}
Длинные, плоские области видимости, как правило, также плохо отражаются на коде. Введение частных методов, чтобы разбить вещи только для этой цели, также неслыханно.
В условиях ограничения памяти (например, в мобильных телефонах) это может быть полезно. При установке значения null объект не должен ждать, пока переменная выйдет из области видимости, чтобы быть gc'd.
Однако для повседневного программирования это не должно быть правилом, за исключением особых случаев, подобных тому, который цитировал Крис Джестер-Янг.
Во-первых, это не означает, что вы устанавливаете объект на 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 будет управлять мной".
Надеюсь, это прояснит концепцию.
Одна из причин для этого - исключить устаревшие ссылки на объекты. Вы можете прочитать текст здесь.