Trabajo en una aplicación Tomcat que utiliza el colector CMS junto con una barra de memoria para activar GC. Cuando vuelvo a cargar las webapps, a veces termino en una situación en la que el viejo generador está lo suficientemente lleno como para activar el GC, pero los cargadores de clase muertos no se recogen.¿Cuándo se recoge el gen de la permanente?
Leí que las clases se asignan al generador de perm e intuí que, por lo tanto, las antiguas colecciones de gen estaban ignorando. Escribí la siguiente clase de prueba para probar esta teoría.
package test;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
/*
JVM Options:
-server -XX:+UseMembar -XX:+UseConcMarkSweepGC
-XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=80
-XX:+UseCMSInitiatingOccupancyOnly -Xms100m -Xmx100m
-XX:PermSize=100m -XX:NewSize=10m -XX:MaxNewSize=10m
-verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
*/
public class ClassLoaderTest extends ClassLoader
{
@Override
protected synchronized Class<?> loadClass(String xiName, boolean xiResolve)
throws ClassNotFoundException
{
if (xiName.equals("test"))
{
// When asked to load "test", load Example.class
Class<?> c = Example.class;
String className = c.getName();
String classAsPath = className.replace('.', '/') + ".class";
InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);
byte[] classData = null;
try
{
classData = IOUtils.toByteArray(stream);
}
catch (IOException e)
{
e.printStackTrace();
}
return defineClass(className, classData, 0, classData.length);
}
return super.loadClass(xiName, xiResolve);
}
public static class Example {}
public static ClassLoaderTest classLoaderTest;
public static void main(String[] args) throws Exception
{
// Allocate CL in new gen
classLoaderTest = new ClassLoaderTest();
// Load a class - allocated in perm gen
classLoaderTest.loadClass("test");
// Discard CL
classLoaderTest = null;
// Pause at end
Thread.sleep(99 * 60 * 1000);
}
public final byte[] mMem = new byte[85 * 1024 * 1024];
}
que corrió esta clase y supervisa la salida usando VisualVM y vio que había hecho varias colecciones antiguas y generación joven que suceden sin el cargador de clase muertos siendo recogidos y por ello la gran matriz de bytes permanecieron en la memoria.
Lo que daría lugar a la ondulación permanente Gen a cobrar?
¿Sabía que "Perm" es la abreviatura de [... ¿correcto?] (Http://en.wiktionary.org/wiki/permanent#Adjective) –
La memoria asignada en Java Perm Gen aún se puede recopilar. La JVM usa Perm Gen para contener datos que espera que se liberen muy raramente. – mchr