Я задал вопрос о Сборке "мусора" в Java в этой теме. Но ответ, который я получил, дал мне другой вопрос.
Кто-то упомянул, что классы могут быть собраны сборщиком "мусора" также. Действительно ли это верно?
И если это верно, как это работает?
Класс в 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
) имеют право на сборку мусора.