Я задал вопрос о Garbage Collection на Java в в этом разделе. Но ответ, который я получил, дал мне еще один вопрос.
Кто-то сказал, что классы могут быть собраны сборщиком мусора. Это правда?
И если это так, как это работает?
Я задал вопрос о Garbage Collection на Java в в этом разделе. Но ответ, который я получил, дал мне еще один вопрос.
Кто-то сказал, что классы могут быть собраны сборщиком мусора. Это правда?
И если это так, как это работает?
Класс в Java может быть собран с помощью мусора, когда ничего не ссылается на него. В большинстве простых настроек это никогда не происходит, но бывают ситуации, когда это может произойти.
Существует множество способов сделать доступный класс доступным и, следовательно, не позволяет ему иметь доступ к GC:
Class
, представляющий класс, все еще доступенClassLoader
, который загрузил класс, все еще доступенClassLoader
, по-прежнему доступныЕсли ни один из них не является истинным, то ClassLoader
и все классы, которые он загрузил, имеют право на GC.
Вот построенный пример (полный плохих практик!), который должен продемонстрировать поведение:
Создайте файл байт-кода 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
приведет к созданию этого (или подобного) вывода:
in main Creating ClassLoader Loading Class Getting static field Reading static value [email protected] created Got value: [email protected] First gc() call Second gc() call (in main) [email protected] finalized End of main
Во второй-последней строке мы видим, что экземпляр GCTester
финализирован, что может означать только то, что класс (и ClassLoader
) имеет право на сбор мусора.