Чи відкриті статичні поля для збору сміття?


95

Враховуючи гіпотетичний клас корисності, який використовується лише при налаштуванні програми:

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

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

Відповіді:


112

Статичні змінні не можуть бути обрані для збору сміття під час завантаження класу. Їх можна збирати, коли відповідний навантажувач класу (який відповідав за завантаження цього класу) сам збирає для сміття.

Перегляньте розділ 12.7 JLS Розвантаження класів та інтерфейсів

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


@bruno, за вашим посиланням, чи означає це, що завантажувач класів містить посилання на кожен клас, який він завантажує, навіть якщо в завантаженому класі немає статичних членів?
Pacerier

@brunoconde, я не думаю, що це насправді правда. Точно в якому абзаці зазначено це? (Будь ласка , продовжуйте обговорення stackoverflow.com/questions/405364 / ... )
Pacerier

Коли навантажувач класу міг би приймати сміття. ?
Rohit Bandil

@RohitBandil - коли це недосяжно.
Стівен C

55

На статичні змінні посилаються об’єкти класу, на які посилаються ClassLoaders - отже, якщо або ClassLoader якось не скидає клас (якщо це можливо), або сам ClassLoader стає придатним для збору (більш імовірно - подумайте про розвантаження веб-додатків) статичних змінних (або швидше, об'єкти, на які вони посилаються) не збиратимуться.


1
Чи Classпосилаються на об’єкти, які не містять статичних змінних, завантажувач класу?
Pacerier

14

Якщо ви хочете, щоб тимчасовий об'єкт використовувався для статичної ініціалізації, після чого утилізувався, ви можете використовувати блок статичного ініціалізатора, наприклад

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

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

оскільки блок статичного ініціалізатора є особливим видом статичного методу, myObject є локальною змінною і може бути зібраний сміття після закінчення виконання блоку.


13

myObject - це посилання, а не об'єкт . Об’єкт автоматично збирається сміттям, коли на нього не вказує посилання, оскільки він недоступний.

Таким чином, об'єкт, що стоїть за статичним посиланням "myObject", може бути зібраним сміттям, якщо ви його визначите

myObject = null;

і інших посилань на цей об’єкт немає.

Однак статичні посилання та змінні залишаються впродовж життя вашої програми.


Ласкаво просимо до StackOverflow! Встановлення об'єкта nullв кінці пункту static blockє життєздатним варіантом. Однак у моєму випадку час життя об’єкта повинен був бути довшим за статичний блок. Кінцева корисність об’єкта була не дуже конкретна; таким чином, я запитую про використання сміттєзбірника.
Майкл Дірдеуфф

7

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


0

Ключовим тут є колекція сміття екземплярів класу, тобто об’єктів. Екземпляр ClassLoader - це, по суті, Об'єкт. Тож якщо об’єкт Classloader не збирає сміття, будь-які посилання на них, що зберігаються в купі (тобто статичні речі), майже ніколи не збираються сміттям. Виняток становить String pool.

Тому перш ніж раптом вирішити задуматися, private static MyGiantClass myGiantObject = new MyGiantClass() подумайте двічі, як я навчився важкого шляху.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.