Открыты ли статические поля для сборки мусора?

Учитывая гипотетический служебный класс, который используется только при настройке программы:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

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


person Michael Deardeuff    schedule 17.01.2009    source источник


Ответы (6)


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

Ознакомьтесь с раздел 12.7 JLS, выгрузка классов и интерфейсы

Класс или интерфейс могут быть выгружены тогда и только тогда, когда его определяющий загрузчик классов может быть возвращен сборщиком мусора [...] Классы и интерфейсы, загруженные загрузчиком начальной загрузки, не могут быть выгружены.

person bruno conde    schedule 17.01.2009
comment
@bruno, по вашей ссылке, означает ли это, что загрузчик классов содержит ссылку на каждый загружаемый класс, даже если загруженный класс не имеет статических членов? - person Pacerier; 23.08.2014
comment
@brunoconde, на самом деле я не думаю, что это правда. В каком именно абзаце это сказано? (Продолжайте обсуждение stackoverflow.com/questions/405364/) - person Pacerier; 24.08.2014
comment
Когда загрузчик классов будет иметь право на сборку мусора. ? - person Rohit Bandil; 15.09.2016
comment
@RohitBandil - когда он недоступен. - person Stephen C; 21.01.2018

На статические переменные ссылаются объекты класса, на которые ссылается ClassLoaders -so, если либо ClassLoader каким-то образом не отбрасывает класс (если это даже возможно), либо сам ClassLoader не становится подходящим для сбора (более вероятно - подумайте о выгрузке веб-приложений) статических переменных (или скорее объекты, на которые они ссылаются) не будут собраны.

person Jon Skeet    schedule 17.01.2009
comment
На Class объекты, не содержащие статических переменных, ссылается их загрузчик классов? - person Pacerier; 23.08.2014

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

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

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

person finnw    schedule 17.01.2009

myObject - это ссылка, а не объект. Объект автоматически собирает мусор, если на него нет ссылок, потому что он недоступен.

Таким образом, объект за статической ссылкой «myObject» может быть удален сборщиком мусора, если разыменовать его с помощью

myObject = null;

и других ссылок на этот объект нет.

Однако статические ссылки и переменные остаются в течение всего срока службы вашей программы.

person Felix Keil    schedule 11.07.2014
comment
Добро пожаловать в StackOverflow! Установка объекта в null в конце static block - приемлемый вариант. Однако в моем случае время жизни объекта должно быть больше, чем у статического блока. Конец полезности объекта не был очень конкретным; поэтому я спрашиваю об использовании сборщика мусора. - person Michael Deardeuff; 11.07.2014

Я думаю, что это ответит на ваш вопрос - в основном, если только класс не исходит из специальный загрузчик классов, который выгружает класс.

person Tom    schedule 17.01.2009

Ключевым моментом здесь является сборка мусора экземпляров класса, то есть объектов. Экземпляр ClassLoader, по сути, является объектом. Таким образом, если объект Classloader не является сборщиком мусора, любые ссылки на него, хранящиеся в куче (т.е. статический материал), почти никогда не будут собираться сборщиком мусора. Исключение составляет пул строк.

Итак, прежде чем вы вдруг решите сделать private static MyGiantClass myGiantObject = new MyGiantClass() Подумайте дважды, поскольку я выучил на собственном горьком опыте.

person ha9u63ar    schedule 02.05.2018