Una clase en Java se puede recolectar basura cuando nada hace referencia a ella. En la mayoría de las configuraciones simples, esto nunca sucede, pero hay situaciones en las que puede ocurrir.
Hay muchas maneras de hacer una clase accesible y así evitar que sea elegible para GC:
- objetos de esa clase son todavía accesibles.
- el objeto
Class
que representa la clase es todavía alcanzable
- la
ClassLoader
que carga la clase es todavía alcanzable
- otras clases cargadas por el
ClassLoader
son todavía alcanzable
Cuando ninguno de los que son verdaderas , entonces el ClassLoader
y todas las clases que cargó son elegibles para GC.
Aquí está un ejemplo de construcción que deben demostrar el comportamiento (lleno de malas prácticas!):
Crear un archivo de código de bytes GCTester.class
en un directorio (no paquete!) x
. Es el código fuente es:
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");
}
}
A continuación, cree una clase TestMe
en el directorio padre 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);
}
}
Correr TestMe
producirá este (o similar) de salida:
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 penúltima línea vemos que la instancia GCTester
está finalizada, lo que solo puede significar que la clase (y)) son elegibles para la recolección de basura.
Puede resultar útil este tema: http://stackoverflow.com/questions/453023/are-static-fields-open-for-garbage-collection –
Éste también: "Cuándo y cómo se marca un cargador de clases java para la recolección de basura? " http://stackoverflow.com/questions/2344964/when-and-how-is-a-java-classloader-marked-for-garbage-collection – ewernli