Когда и как классы собраны "мусор" в Java?

Я задал вопрос о Сборке "мусора" в Java в этой теме. Но ответ, который я получил, дал мне другой вопрос.

Кто-то упомянул, что классы могут быть собраны сборщиком "мусора" также. Действительно ли это верно?

И если это верно, как это работает?

27
задан Community 23 May 2017 в 12:25
поделиться

1 ответ

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

Есть много способов сделать класс доступным и, таким образом, предотвратить его право на сборку мусора:

  • объекты этого класса по-прежнему достижимы.
  • объект Class , представляющий класс, все еще доступен
  • ClassLoader , который загрузил класс, все еще доступен
  • другие классы, загруженные ClassLoader ] по-прежнему доступны

Если нет из них истинны, то ClassLoader и все загруженные им классы имеют право на сборку мусора.

Вот сконструированный пример (полный недобросовестных действий!), Который должен продемонстрировать поведение:

Создайте файл байт-кода GCTester.class в каталоге (не в пакете!) x ]. Его исходный код:

public class GCTester {
  public static final GCTester INSTANCE=new GCTester();

  private GCTester() {
    System.out.println(this + " created");
  }

  public void finalize() {
    System.out.println(this + " finalized");
  }
}

Затем создайте класс TestMe в родительском каталоге x :

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Field;

public class TestMe {
  public static void main(String[] args) throws Exception {
    System.out.println("in main");
    testGetObject();
    System.out.println("Second gc() call (in main)");
    System.gc();
    Thread.sleep(1000);
    System.out.println("End of main");
  }

  public static void testGetObject() throws Exception {
    System.out.println("Creating ClassLoader");
    ClassLoader cl = new URLClassLoader(new URL[] {new File("./x").toURI().toURL()});
    System.out.println("Loading Class");
    Class<?> clazz = cl.loadClass("GCTester");

    System.out.println("Getting static field");
    Field field = clazz.getField("INSTANCE");

    System.out.println("Reading static value");
    Object object = field.get(null);
    System.out.println("Got value: " + object);

    System.out.println("First gc() call");
    System.gc();
    Thread.sleep(1000);
  }
}

Запуск TestMe создаст это (или подобное) output:

in main
Creating ClassLoader
Loading Class
Getting static field
Reading static value
GCTester@1feed786 created
Got value: GCTester@1feed786
First gc() call
Second gc() call (in main)
GCTester@1feed786 finalized
End of main

Во второй предпоследней строке мы видим, что экземпляр GCTester завершен, что может означать только то, что класс (и ClassLoader ) имеют право на сборку мусора.

31
ответ дан 28 November 2019 в 05:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: