Как правильно удалить массив в Java

Мне 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;...

@ТТ. хотя ответ тот же, мой вопрос касался именно массивов. Это означает, что даже если бы я прочитал это до того, как спросил, у меня все равно были бы сомнения (с нубийной точки зрения)

Chronus 08.04.2019 09:38

Хорошо, я слышу тебя. Знайте, что все, кроме примитивных типов данных (например, int, double,...) являются объектами. Важно знать.

TT. 08.04.2019 09:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
13
2
5 009
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В какой-то момент после того, как массив выйдет за пределы области видимости, сборщик мусора освободит память, если на нее нет других ссылок.

Если вы хотите обнулить свою ссылку до того, как переменная выйдет из области видимости (имейте в виду, что если в каком-то другом коде есть эта ссылка, она не будет собирать мусор):

Foo[][] fooArray = new Foo[2][3];

...

// this will null the reference to the array
fooArray = null;

Ваша формулировка («один раз») звучит так, как будто память будет восстановлена ​​как только, последняя ссылка выходит за рамки. Это довольно важное свойство Java GC, что это не тот случай.

Konrad Rudolph 08.04.2019 11:24

Хорошее замечание - отредактировано.

Jason 09.04.2019 00:24

В отличие от C, Java обеспечивает автоматическую сборку мусора, которая очистит массив для вас, когда он станет недоступным (т.е. выйдет за пределы области видимости). Если вы хотите, вы можете сделать массив нулевым, чтобы ячейка памяти стала недоступной.

    Foo[][] fooArray = new Foo[2][3];
    .
    .
    .
    fooArray = null;
    System.gc();

Этот вызов gc не гарантирует, что JVM запустит сборщик мусора, но предполагает, что виртуальная машина Java затрачивает усилия на переработку неиспользуемых объектов, чтобы сделать память, которую они в настоящее время занимают, доступной для быстрого повторного использования. Когда управление возвращается из вызова метода, виртуальная машина Java приложила все усилия, чтобы освободить место от всех отброшенных объектов.

Не вижу смысла предлагать System#gc. В большинстве случаев это приведет к снижению производительности. Пусть сборщик мусора делает свою работу. Обычно он используется только для очистки перед измерением (профилировщик и другие инструменты).

Zabuzard 08.04.2019 09:15

Я согласен с вами, но в некоторых случаях может иметь смысл предложить JVM выполнить полную сборку СЕЙЧАС, поскольку вы можете знать, что приложение будет бездействовать в течение следующих нескольких минут перед тяжелой работой.

Vaibhav Gupta 08.04.2019 09:18

@Vaibhav Gupta Сборщик мусора не Чисто массив, он только освобождает его. Вредоносное ПО может получить доступ к данным, иногда в течение длительного времени, пока память не будет повторно использована. Если массив содержит конфиденциальные данные, он должен быть активно очищен перед выпуском.

Jonathan Rosenne 08.04.2019 09:52
Ответ принят как подходящий

Объяснение

Вы не можете явно удалить что-то в Java. Это задача сборщиков мусора. Он удалит все, что больше никем не используется. Так что либо

  1. позволить переменной выйти из области видимости или
  2. назначить null
  3. или любой другой экземпляр к нему.

Тогда экземпляр массива (а также его подмассивы) будет больше не упоминается, и сборщик мусора в конечном итоге удалит его.


использованная литература

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

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».

Boris the Spider 08.04.2019 12:26

Это абсолютно правильно и хорошее замечание! Но я чувствую, что это излишне усложнит ответ.

Zabuzard 08.04.2019 12:34

@BoristheSpider Я думаю, что «не упоминается» - хороший выбор слов, поскольку все упоминается в java, просто, возможно, не обязательно из java-объектов, а из внутренних компонентов jvm (например, переменные стека, загруженные экземпляры java.lang.Class, ... ) (последние случаи отмечены вместе как корни GC). Так что я бы по-прежнему называл это «ссылочным».

bwoebi 08.04.2019 14:25

«Не упоминается» не совсем правильно. «Не указан» означает, что два объекта, которые ссылаются друг на друга, или один объект, который ссылается сам на себя, не будут удалены, что явно неверно. Сборщики мусора не удаляют объекты, на которые «не ссылаются», они удаляют объекты, которые не являются доступный, из корня GC (работающего потока). Когда null присваивается outer, весь массив и все внутренние массивы становятся не доступный программой, и все сметаются за один раз. Нет необходимости сначала удалять внешний массив, чтобы обнаружить, что внутренние массивы также могут быть удалены.

Boann 08.04.2019 18:34

^ это. Вот почему используемая терминология проблематична и на самом деле может вызвать еще большую путаницу.

Boris the Spider 10.04.2019 08:22

Будьте моим гостем и исправьте условия. Но я думаю, что лучше сделать это простым, а затем добавить раздел со ссылкой на более глубокое объяснение, быстро резюмируя, как это работает, в двух предложениях.

Zabuzard 10.04.2019 09:12

Фраза хороша для первой, вводной части, но я отредактировал предложение во второй части, так как это полезно для читателей, когда терминология совпадает с той, что можно найти в другой литературе (если они заинтересованы в более подробной информации). Я также добавил ссылку на спецификацию. И я думаю, что важно говорить «может», а не «будет», поскольку сборка мусора намеренно недетерминирована. На самом деле, даже термин «удалить» не соответствует тому, что происходит на самом деле, но я думаю, что лучше оставить его таким, так как там достаточно дополнительной литературы.

Holger 12.04.2019 09:41

Другие вопросы по теме