Какой объект будет собирать мусор? - PullRequest
1 голос
/ 20 января 2010

Я хочу подтвердить, какой сценарий вызовет сборку мусора для объекта myObj:

Сценарий 1

ArrayList arList = new ArrayList();
while(someCondition)
{
  myObj = new MyObect(); // a custom object
  arList.add(myObj); 
}

Сценарий 2

ArrayList arList = new ArrayList();
while(someCondition)
{
  myObj = new MyObect(); // a custom object
  arList.add(myObj); 
  myObj=null;
}

Улучшает ли явное задание объекта как null поведение сборки мусора или оно будет таким же, когда я сбрасываю объект с помощью нового конструктора?

Ответы [ 4 ]

7 голосов
/ 20 января 2010

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

Обновление: , учитывая обновленную информацию о том, что myObj является локальным для метода, будет иметь нулевое значение, чтобы установить его на null в конце каждой итерации цикла. Рассмотрим этот пример:

public void process(String text) {
  String[] lines = text.split("\n");
  List<MyObject> list = new ArrayList<MyObject>();
  Object myObj;
  for (String line : lines) {
    myObj = new MyObject(line);
    list.add(myObj);
    // 1. set myObj = null here
  }
  list = null; // 2
  // 3. do some other stuff
}

public class MyObject {
  private final String line;

  public MyObject(String line) {
    this.line = line;
  }
}

Теперь в этом примере, скажем, на шаге 3 это заняло много времени. Скажи 10 минут. В течение этих 10 минут myObj указывает на последнюю обработанную строку. Не похоже на проблему? Ну, это может быть. Подстроки работают в Java так, что они ссылаются на исходную строку. Так что если вы делаете:

String s = ... // 100 megabytes
String s2 = s.substring(100, 101);

вы на самом деле храните все 100 МБ в памяти, потому что s2 ссылается на s.

Так что в функции, которую я имею выше, myObj ссылается на строку, которая ссылается на весь файл. Изменение шага 1 на myObj = null; действительно поможет, потому что эта ссылка предотвращает сборку мусора для объекта.

Примечание: шаг 2 важен здесь, потому что если бы вы не аннулировали список, все ссылки в любом случае существовали бы.

Вам просто нужно подумать о том, как работают ссылки. Объект не будет собираться мусором, пока существует ссылка на него. Это означает очистку долгоживущих ссылок и поддержание переменных как можно более плотно ограниченных. Правильное решение для вышеизложенного:

for (String line : lines) {
  Object myObj = new MyObject(line);
  ...
}

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

6 голосов
/ 20 января 2010

Установка его на null не будет иметь никакого эффекта, поскольку объект все еще достижим через arList.

То есть ваши MyObect экземпляры будут жить как минимумПока arList.

РЕДАКТИРОВАТЬ : Судя по вашему комментарию, звучит myObj дольше.В этом случае установите значение null после окончания цикла.

2 голосов
/ 20 января 2010

Я думаю, что это корень вашего недопонимания.

хмм ... но я не хочу хранить 2 копии myObj, одну в arList и одну в исходной переменной.Как я могу сбросить myObj, как только я добавлю его в arLsit?

Вы НЕ «храните две копии myObj».В ваших примерах есть только одна «копия» каждого экземпляра MyObject, созданного циклом.Последовательность:

  1. Вы создаете экземпляр MyObject, присваивая его ссылку на myObj.

  2. Вы добавляете ссылку на экземпляр вArrayList, к которому относится arList.

  3. Вы присваиваете null ссылку в myObj.

Обратите внимание, что при добавленииссылка на список НЕ создает копию экземпляра MyObject.Это просто означает, что у вас есть ссылка в двух местах вместо одного.И когда вы присваиваете null, вы снова получаете ссылку только в одном месте.

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

Наконец, если мы предположим, что область видимости следующая, то строка C будет иметьникакого заметного эффекта ... , если ни строка A, ни строка B не запускают сборку мусора.

{
    MyObject myObj;
    ArrayList arList = new ArrayList();
    while (someCondition) {       // A
         myObj = new MyObect();   // B
         arList.add(myObj); 
         myObj = null;            // C
    }
}
1 голос
/ 20 января 2010

Поскольку он находится в while, myObj всегда перезаписывается (ссылка).Таким образом, в сценарии 1 только один объект (последний добавленный в arList) не будет null.

Было бы лучше, если бы вы объявили это в выражении while:

while(someCondition)
{ 
  MyObect myObj = new MyObect(); // a custom object
  arList.add(myObj);  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...