Сколько объектов создается и сколько подлежит сбору мусора?

avatar
xanyamm
1 июля 2021 в 16:07
203
2
0

Учитывая следующий код, сколько объектов создается с помощью функции main() и после выполнения строки 15, сколько объектов подлежит сборке мусора?

class Test
{
    int[] dz = {1, 2, 3, 4, 5};
}

public class MarksDriver
{
    public static void main(String[] args)
    {
        Test[] da = new Test[3];
        da[0] = new Test();
        Test d = new Test();
        da[1] = d;
        d = null;
        da[1] = null;   //line 15
        //some code
    }
}
  1. 3 создано, 0 подходит
  2. 4 создано, 1 подходит
  3. 5 создано, 2 подходящих
  4. 3 создано, 2 подходящих
  5. Ничего из вышеперечисленного

Хорошо, прежде всего, пожалуйста, не отмечайте это как домашнее задание. Это вопрос из теста в моем колледже. По моему мнению, должно быть создано 2 объекта, а 1 подлежит сборке мусора после строки 15. Это связано с тем, что для создания объектов используются только два новых оператора, а объект, на который ссылался «d» в начале, теряется после строка 15, чтобы освободить память. Поэтому я отметил последний вариант, который не является ни одним из вышеперечисленных. Но мой Учитель отметил это неправильно и сказал, что ответ 5,2. Она дала какое-то объяснение, на которое я не намекнул.

Итак, кто-нибудь может это объяснить?

Источник
Eugene
1 июля 2021 в 16:09
0

"Но мой Учитель отметил это неправильно и сказал, что ответ 5,2" - пригласите ее/его сюда. потому что он / она на самом деле тоже не знает ответа.

Michael
1 июля 2021 в 16:13
0

@Eugene Array (da), 2x Test, каждый из которых содержит 1 массив = 5. На массив da по-прежнему ссылаются, как и на значение da[0], оставляя только 2 объекта, подходящих для GC — экземпляр, изначально назначенный Test d, и это массив элементов. Так что ответ правильный.

Eugene
1 июля 2021 в 16:14
2

@Michael, если вы ничего не используете после //some code, то все имеет право на сборщик мусора. Такие вопросы не имеют смысла

xanyamm
1 июля 2021 в 16:16
0

@Michael Но создание массива объектов на самом деле не создает объекты, верно? Он создает ссылки на объекты. И объекты должны создаваться вручную.

Michael
1 июля 2021 в 16:17
0

@xanyamm Создание массива не создает объекты, правильно. Но массив сам по себе является объектом.

Michael
1 июля 2021 в 16:20
0

@Eugene Пример немного надуманный, и они намеренно манипулируют ссылками, но вопрос имеет смысл. Замените //some code на любой допустимый оператор, установите точку останова на этом операторе, запустите его и перечислите, на какие объекты все еще ссылаются, когда он останавливается. Имеет смысл для меня.

xanyamm
1 июля 2021 в 16:21
0

@Michael Хорошо, я понял, но разве массивы-члены не будут инициализированы нулевой ссылкой конструктором по умолчанию?

Michael
1 июля 2021 в 16:24
0

@xanyamm Нет. Есть несколько способов инициализировать поле. То, как это делает ваш пример, находится в точке объявления. Таким образом, каждый экземпляр Test начинается с поля с именем dz, инициализированного новым массивом, содержащим числа от 1 до 5. Числа в массиве являются примитивными типами, поэтому они не учитываются при подсчете количества объектов. См. docs.oracle.com/javase/tutorial/java/javaOO/initial.html.

Eugene
1 июля 2021 в 16:26
0

@Майкл, это твое мнение, и я его уважаю, конечно. То, как этот код и вопрос: «сколько объектов имеют право на GC после строки 15», ответ: все они.

Holger
1 июля 2021 в 17:41
1

@Michael добавление отладчика, который может проверять объекты, означает изменение среды выполнения. Причина, по которой объекты не собираются, заключается в том, что отладчик сам хранит ссылки на эти объекты. Нормальная ситуация описана в разделе Может ли java финализировать объект, когда он все еще находится в области видимости?

Holger
1 июля 2021 в 17:53
1

Странно представлять ответы пронумерованными от одного до пяти и говорить ответ "пять запятая два". Мне потребовалось некоторое время, чтобы понять, что это должно означать. Чтобы устранить вашу путаницу, объявление поля int[] dz = {1, 2, 3, 4, 5}; в классе Test ничем не отличается от объявления поля int[] dz; и конструктора Test() { dz = new int[] {1, 2, 3, 4, 5}; }, который также является просто сокращением для dz = new int[5]; dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 3; dz[4] = 5;. Скомпилированный код будет (почти) одинаковым для всех трех вариантов.

Alan
1 июля 2021 в 19:14
0

@Eugene re «Способ использования этого кода и вопрос: «сколько объектов подходят для GC после строки 15», ответ: все они». ... Комментарий после строки 15 важен для того, чтобы показать, что da [0] нельзя удалить, потому что код после строки 15 может использовать его.

Michael
1 июля 2021 в 20:11
0

@Holger Хорошо, тогда замените отладчик в моем примере волшебным секундомером, который останавливает выполнение. Можем ли мы согласиться с тем, что вопрос совершенно прост, или мы должны теперь обсудить существование такого волшебного секундомера?

Eugene
3 июля 2021 в 00:35
0

@Alan, во-первых, сборщик мусора Java ничего не «удаляет», он может обнулить все (даже это неправильно, поскольку он этого не делает); тогда, если ваша точка зрения верна, то это должно быть инвариантом вопроса. Я могу сказать то же самое: «после комментария ничего нет. Ничего», поэтому все подходит для GC. Для студента профессор задал немой вопрос.

Alan
3 июля 2021 в 03:05
0

@Eugene Да, я знаю, что он не обнуляется автоматически, и ячейки памяти не исчезают с лица земли. Их адреса удаляются из списков памяти на хранение и перемещаются в списки доступной памяти и т. д. Дело в том, что если в этом методе остался код, он мог бы легко получить доступ к da [0], поэтому da [0] не может быть имеет право на сборку мусора, пока это не станет известно, и это не будет соответствовать целям вопроса. Но другие вещи аннулируются и имеют право. Но не все из них. Чтобы иметь право на участие, вы должны быть уверены, что к ним больше не будут обращаться.

Alan
3 июля 2021 в 03:19
0

@Eugene, даже Oracle использует слово «удалить», когда речь идет о сборке мусора: oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/… Это распространенное выражение как сокращение для более сложной машины позади него. Они пишут: «Автоматическая сборка мусора — это процесс просмотра памяти кучи, определения того, какие объекты используются, а какие нет, и удаления неиспользуемых объектов».

Holger
5 июля 2021 в 08:47
1

@ Майкл, нет, это не прямолинейно. Я уже давал вам эту ссылку в этом комментарии. Связанный ответ содержит фактический пример кода, который демонстрирует, что объекты, на которые ссылаются локальные переменные в области видимости, могут собирать мусор в реальной жизни. Таким образом, эти объекты формально подходят для gc ​​и , они могут быть собраны на практике, но вы говорите, что «волшебный секундомер» имеет большее значение, чем спецификация и реальной совместной жизни?

Holger
5 июля 2021 в 10:26
2

@Alan тест колледжа, который предполагает делать предположения о том, что будет делать «какой-то код», не показанный в задаче, в корне ошибочен. Кроме того, как обсуждалось в разделе finalize(), вызываемом для сильно достижимых объектов в Java 8, даже использование объекта не обязательно предотвращает сборку мусора этого объекта; он может быть даже собран (и, в свою очередь, завершен), в то время как вызов метода для этого объекта все еще продолжается. Важно только то, сможет ли JVM доказать, что память объекта больше не нужна. В реальном JIT-оптимизированном коде.

Alan
5 июля 2021 в 10:34
0

@Holger Спасибо за четкое объяснение и интересную ссылку.

Ответы (2)

avatar
Alan
1 июля 2021 в 19:08
0

5 создано, 2 можно удалить

Создаются два объекта Test. Но каждый содержит объект массива, так что всего четыре объекта.

Дополнительно создается массив da. Это 5 объектов.

Когда d равно null, сборщиком мусора могут быть два объекта: массив, который содержит d, и сам d.

...

Возможно, учитель ошибается, и "ничего из вышеперечисленного" не является правильным, потому что основной верный ответ равен 6 и 2, потому что наверняка шестой объект создается: объект <242291432311 !

ehecatl
1 июля 2021 в 19:30
0

Вызов MarksDriver.main() не создает экземпляр класса MarksDriver. JVM вызывает метод main с ненулевым массивом аргументов, даже если он пуст. Однако, если мы считаем аргументы, мы также должны учитывать Test.class, MarksDriver.class и любое количество скрытых объектов JVM. Я думаю, что было создано 5 объектов user, из которых 2 можно удалить, это разумный ответ.

Alan
1 июля 2021 в 19:33
0

@ehecatl Это потому, что MarksDemo не имеет переменных экземпляра/статических переменных? Если бы это было так (скажем, примитивное целое число), то означало бы это, что он фактически создан, потому что переменная должна содержаться?

Holger
5 июля 2021 в 08:59
2

Экземпляр создается, когда программный код содержит new MarksDriver(…). В противном случае экземпляр этого класса не создается, независимо от того, какие переменные вы объявляете в этом классе.

Alan
5 июля 2021 в 10:22
0

@Holger В этом есть смысл. Тоже хороший способ запомнить. Да, это будет доступ. Спасибо. И затем, исходя из этого, я думаю, что статические переменные будут храниться в куче по мере необходимости и управляться ими на уровне класса.

avatar
anish sharma
1 июля 2021 в 18:48
0

Когда мы пишем

 Test d = new Test();

2 объекта созданы, один - d, другой - элемент массива dz

то же самое с

da[0] = new Test();

2 объекта создаются один хранится в da[0], другой является массивом элементов dz

и еще один объект создан

Test[] da = new Test[3];

всего создано 5 объектов

с этими 2 строками кода нет ссылки на один объект теста класса, созданный в строке 13, что делает его пригодным для сборки мусора, что, в свою очередь, также делает массив элементов dz пригодным для сборки мусора, поэтому 2 объекта становятся подходящими для сборка мусора после строки 15

    d = null;
    da[1] = null;