Une classe en Java peut être collectée sans que rien ne la mentionne. Dans la plupart des configurations simples, cela n'arrive jamais, mais il y a des situations où cela peut se produire.
Il y a plusieurs façons de faire une classe accessible et empêcher ainsi d'être admissible à GC:
- objets de cette classe sont encore accessibles.
- l'objet
Class
représentant la classe est toujours accessible
- le
ClassLoader
qui a chargé la classe est toujours accessible
- autres classes chargées par le
ClassLoader
sont encore accessibles
Lorsque aucun de ceux sont vraies , puis ClassLoader
et toutes les classes chargées sont éligibles pour GC.
Voici un exemple construit qui doit démontrer le comportement (plein de mauvaises pratiques!):
Créer un fichier bytecode GCTester.class
dans un répertoire (paquet pas!) x
. Il est le code source est:
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");
}
}
Ensuite, créez une classe TestMe
dans le répertoire parent de 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);
}
}
L'exécution TestMe
produira ce (ou similaire) Sortie:
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
En la deuxième à la dernière ligne, nous voyons que l'instance GCTester
est finalisée, ce qui peut seulement signifier que la classe (et ClassLoader
) sont éligibles pour la collecte des ordures.
Vous pouvez trouver ce sujet utile: http://stackoverflow.com/questions/453023/are-static-fields-open-for-garbage-collection –
Celui-ci aussi: "Quand et comment un classloader java est marqué pour la collecte des ordures? " http://stackoverflow.com/questions/2344964/when-and-how-is-a-java-classloader-marked-for-garbage-collection – ewernli