Мне 4 дня на Java, и из учебников, которые я искал, инструкторы уделяют много усилий объяснению того, как выделить двумерный массив (например) как таковой:
Foo[][] fooArray = new Foo[2][3];
... но я не нашел ничего, что объясняло бы, как их удалить.
Судя по тому, что происходит с памятью, переменная fooArray
будет указывать на блок памяти в куче, в котором 2 элемента. Каждый из элементов также указывает на другой блок в куче, который имеет 3 элемента.
При этом могу ли я просто сослаться на первый блок элементов, и сборщик мусора выполнит эту работу?
Foo[1] = null;
и Foo[2] = null;
Или мне нужно обнулить каждый из созданных элементов Foo?
Foo[1][1] = null;
Foo[1][2] = null;
Foo[1][3] = null;
...
Хорошо, я слышу тебя. Знайте, что все, кроме примитивных типов данных (например, int, double,...) являются объектами. Важно знать.
В какой-то момент после того, как массив выйдет за пределы области видимости, сборщик мусора освободит память, если на нее нет других ссылок.
Если вы хотите обнулить свою ссылку до того, как переменная выйдет из области видимости (имейте в виду, что если в каком-то другом коде есть эта ссылка, она не будет собирать мусор):
Foo[][] fooArray = new Foo[2][3];
...
// this will null the reference to the array
fooArray = null;
Ваша формулировка («один раз») звучит так, как будто память будет восстановлена как только, последняя ссылка выходит за рамки. Это довольно важное свойство Java GC, что это не тот случай.
Хорошее замечание - отредактировано.
В отличие от C, Java обеспечивает автоматическую сборку мусора, которая очистит массив для вас, когда он станет недоступным (т.е. выйдет за пределы области видимости). Если вы хотите, вы можете сделать массив нулевым, чтобы ячейка памяти стала недоступной.
Foo[][] fooArray = new Foo[2][3];
.
.
.
fooArray = null;
System.gc();
Этот вызов gc не гарантирует, что JVM запустит сборщик мусора, но предполагает, что виртуальная машина Java затрачивает усилия на переработку неиспользуемых объектов, чтобы сделать память, которую они в настоящее время занимают, доступной для быстрого повторного использования. Когда управление возвращается из вызова метода, виртуальная машина Java приложила все усилия, чтобы освободить место от всех отброшенных объектов.
Не вижу смысла предлагать System#gc
. В большинстве случаев это приведет к снижению производительности. Пусть сборщик мусора делает свою работу. Обычно он используется только для очистки перед измерением (профилировщик и другие инструменты).
Я согласен с вами, но в некоторых случаях может иметь смысл предложить JVM выполнить полную сборку СЕЙЧАС, поскольку вы можете знать, что приложение будет бездействовать в течение следующих нескольких минут перед тяжелой работой.
@Vaibhav Gupta Сборщик мусора не Чисто массив, он только освобождает его. Вредоносное ПО может получить доступ к данным, иногда в течение длительного времени, пока память не будет повторно использована. Если массив содержит конфиденциальные данные, он должен быть активно очищен перед выпуском.
Вы не можете явно удалить что-то в Java. Это задача сборщиков мусора. Он удалит все, что больше никем не используется. Так что либо
null
Тогда экземпляр массива (а также его подмассивы) будет больше не упоминается, и сборщик мусора в конечном итоге удалит его.
Чтобы понять, почему переназначения внешнего массива достаточно для удаления внутренних массивов, вам нужно понять, как на них ссылаются. Опять же, сборщик мусора может удалить все, что соответствует недоступный. Итак, давайте посмотрим на такой массив, как:
int[][] outer = {{1, 2}, {3, 4}, {5, 6}};
У нас есть 4 экземпляра массива. Один типа int[][]
и три типа int[]
. Также у нас есть одна переменная outer
. Экземпляры упоминаются следующим образом:
___> {1, 2}
|
outer --> int[][] ---|---> {3, 4}
|
|___> {5, 6}
Таким образом, удаляя outer
, никто больше не ссылается на int[][]
. Теперь сборщик мусора может удалить его. Но это также удаляет все ссылки на внутренние массивы, поэтому сборщик мусора теперь также может их удалить.
Теперь предположим, что вы бы ссылались на один из внутренних массивов с помощью другой переменной:
int[][] outer = {{1, 2}, {3, 4}, {5, 6}};
int[] thirdInner = outer[2];
other = null; // remove the reference
Ситуация сейчас
outer --> null
___> {1, 2}
|
int[][] ---|---> {3, 4}
|
|______> {5, 6}
|
thirdInner _______________|
Итак, теперь сборщик мусора удалит внешний массив int[][]
, который также удалит все ссылки на первый и второй внутренние массивы. Но на третью по-прежнему ссылается thirdInner
, поэтому после сборки мусора имеем:
outer --> null
thirdInner --> {5, 6}
«Не упоминается» сложно, поскольку в какой-то момент все «не упоминается». Правильный язык «недоступен по жестким ссылкам из корня GC».
Это абсолютно правильно и хорошее замечание! Но я чувствую, что это излишне усложнит ответ.
@BoristheSpider Я думаю, что «не упоминается» - хороший выбор слов, поскольку все упоминается в java, просто, возможно, не обязательно из java-объектов, а из внутренних компонентов jvm (например, переменные стека, загруженные экземпляры java.lang.Class, ... ) (последние случаи отмечены вместе как корни GC). Так что я бы по-прежнему называл это «ссылочным».
«Не упоминается» не совсем правильно. «Не указан» означает, что два объекта, которые ссылаются друг на друга, или один объект, который ссылается сам на себя, не будут удалены, что явно неверно. Сборщики мусора не удаляют объекты, на которые «не ссылаются», они удаляют объекты, которые не являются доступный, из корня GC (работающего потока). Когда null
присваивается outer
, весь массив и все внутренние массивы становятся не доступный программой, и все сметаются за один раз. Нет необходимости сначала удалять внешний массив, чтобы обнаружить, что внутренние массивы также могут быть удалены.
^ это. Вот почему используемая терминология проблематична и на самом деле может вызвать еще большую путаницу.
Будьте моим гостем и исправьте условия. Но я думаю, что лучше сделать это простым, а затем добавить раздел со ссылкой на более глубокое объяснение, быстро резюмируя, как это работает, в двух предложениях.
Фраза хороша для первой, вводной части, но я отредактировал предложение во второй части, так как это полезно для читателей, когда терминология совпадает с той, что можно найти в другой литературе (если они заинтересованы в более подробной информации). Я также добавил ссылку на спецификацию. И я думаю, что важно говорить «может», а не «будет», поскольку сборка мусора намеренно недетерминирована. На самом деле, даже термин «удалить» не соответствует тому, что происходит на самом деле, но я думаю, что лучше оставить его таким, так как там достаточно дополнительной литературы.
@ТТ. хотя ответ тот же, мой вопрос касался именно массивов. Это означает, что даже если бы я прочитал это до того, как спросил, у меня все равно были бы сомнения (с нубийной точки зрения)