Учитывая следующий код, сколько объектов создается с помощью функции 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
}
}
- 3 создано, 0 подходит
- 4 создано, 1 подходит
- 5 создано, 2 подходящих
- 3 создано, 2 подходящих
- Ничего из вышеперечисленного
Хорошо, прежде всего, пожалуйста, не отмечайте это как домашнее задание. Это вопрос из теста в моем колледже. По моему мнению, должно быть создано 2 объекта, а 1 подлежит сборке мусора после строки 15. Это связано с тем, что для создания объектов используются только два новых оператора, а объект, на который ссылался «d» в начале, теряется после строка 15, чтобы освободить память. Поэтому я отметил последний вариант, который не является ни одним из вышеперечисленных. Но мой Учитель отметил это неправильно и сказал, что ответ 5,2. Она дала какое-то объяснение, на которое я не намекнул.
Итак, кто-нибудь может это объяснить?
"Но мой Учитель отметил это неправильно и сказал, что ответ 5,2" - пригласите ее/его сюда. потому что он / она на самом деле тоже не знает ответа.
@Eugene Array (da), 2x Test, каждый из которых содержит 1 массив = 5. На массив
da
по-прежнему ссылаются, как и на значениеda[0]
, оставляя только 2 объекта, подходящих для GC — экземпляр, изначально назначенныйTest d
, и это массив элементов. Так что ответ правильный.@Michael, если вы ничего не используете после
//some code
, то все имеет право на сборщик мусора. Такие вопросы не имеют смысла@Michael Но создание массива объектов на самом деле не создает объекты, верно? Он создает ссылки на объекты. И объекты должны создаваться вручную.
@xanyamm Создание массива не создает объекты, правильно. Но массив сам по себе является объектом.
@Eugene Пример немного надуманный, и они намеренно манипулируют ссылками, но вопрос имеет смысл. Замените
//some code
на любой допустимый оператор, установите точку останова на этом операторе, запустите его и перечислите, на какие объекты все еще ссылаются, когда он останавливается. Имеет смысл для меня.@Michael Хорошо, я понял, но разве массивы-члены не будут инициализированы нулевой ссылкой конструктором по умолчанию?
@xanyamm Нет. Есть несколько способов инициализировать поле. То, как это делает ваш пример, находится в точке объявления. Таким образом, каждый экземпляр
Test
начинается с поля с именемdz
, инициализированного новым массивом, содержащим числа от 1 до 5. Числа в массиве являются примитивными типами, поэтому они не учитываются при подсчете количества объектов. См. docs.oracle.com/javase/tutorial/java/javaOO/initial.html.@Майкл, это твое мнение, и я его уважаю, конечно. То, как этот код и вопрос: «сколько объектов имеют право на GC после строки 15», ответ: все они.
@Michael добавление отладчика, который может проверять объекты, означает изменение среды выполнения. Причина, по которой объекты не собираются, заключается в том, что отладчик сам хранит ссылки на эти объекты. Нормальная ситуация описана в разделе Может ли java финализировать объект, когда он все еще находится в области видимости?
Странно представлять ответы пронумерованными от одного до пяти и говорить ответ "пять запятая два". Мне потребовалось некоторое время, чтобы понять, что это должно означать. Чтобы устранить вашу путаницу, объявление поля
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;
. Скомпилированный код будет (почти) одинаковым для всех трех вариантов.@Eugene re «Способ использования этого кода и вопрос: «сколько объектов подходят для GC после строки 15», ответ: все они». ... Комментарий после строки 15 важен для того, чтобы показать, что da [0] нельзя удалить, потому что код после строки 15 может использовать его.
@Holger Хорошо, тогда замените отладчик в моем примере волшебным секундомером, который останавливает выполнение. Можем ли мы согласиться с тем, что вопрос совершенно прост, или мы должны теперь обсудить существование такого волшебного секундомера?
@Alan, во-первых, сборщик мусора Java ничего не «удаляет», он может обнулить все (даже это неправильно, поскольку он этого не делает); тогда, если ваша точка зрения верна, то это должно быть инвариантом вопроса. Я могу сказать то же самое: «после комментария ничего нет. Ничего», поэтому все подходит для GC. Для студента профессор задал немой вопрос.
@Eugene Да, я знаю, что он не обнуляется автоматически, и ячейки памяти не исчезают с лица земли. Их адреса удаляются из списков памяти на хранение и перемещаются в списки доступной памяти и т. д. Дело в том, что если в этом методе остался код, он мог бы легко получить доступ к
da [0]
, поэтомуda [0]
не может быть имеет право на сборку мусора, пока это не станет известно, и это не будет соответствовать целям вопроса. Но другие вещи аннулируются и имеют право. Но не все из них. Чтобы иметь право на участие, вы должны быть уверены, что к ним больше не будут обращаться.@Eugene, даже Oracle использует слово «удалить», когда речь идет о сборке мусора: oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/… Это распространенное выражение как сокращение для более сложной машины позади него. Они пишут: «Автоматическая сборка мусора — это процесс просмотра памяти кучи, определения того, какие объекты используются, а какие нет, и удаления неиспользуемых объектов».
@ Майкл, нет, это не прямолинейно. Я уже давал вам эту ссылку в этом комментарии. Связанный ответ содержит фактический пример кода, который демонстрирует, что объекты, на которые ссылаются локальные переменные в области видимости, могут собирать мусор в реальной жизни. Таким образом, эти объекты формально подходят для gc и , они могут быть собраны на практике, но вы говорите, что «волшебный секундомер» имеет большее значение, чем спецификация и реальной совместной жизни?
@Alan тест колледжа, который предполагает делать предположения о том, что будет делать «какой-то код», не показанный в задаче, в корне ошибочен. Кроме того, как обсуждалось в разделе finalize(), вызываемом для сильно достижимых объектов в Java 8, даже использование объекта не обязательно предотвращает сборку мусора этого объекта; он может быть даже собран (и, в свою очередь, завершен), в то время как вызов метода для этого объекта все еще продолжается. Важно только то, сможет ли JVM доказать, что память объекта больше не нужна. В реальном JIT-оптимизированном коде.
@Holger Спасибо за четкое объяснение и интересную ссылку.