Lavoro su un'applicazione Tomcat che utilizza il raccoglitore CMS insieme a una barra di memoria per attivare GC. Quando ricarico webapps, a volte finisco in una situazione in cui il vecchio gen è abbastanza pieno da innescare GC ma i Classloader morti non vengono raccolti.Quando viene raccolta la perm gen?
Ho letto che le classi sono allocate nel perm gen e ho intuito che venivano quindi ignorate dalle raccolte di vecchie generazioni. Ho scritto la seguente classe di test per testare questa teoria.
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];
}
mi sono imbattuto questa classe e monitorare l'output utilizzando VisualVM e ho visto che ci sono stati effettivamente più vecchi e giovani generazione collezioni che accadono senza il programma di caricamento classi morti essere raccolti e quindi il grande array di byte rimasti in memoria.
Cosa farebbe scattare l'Perm Gen da raccogliere?
Sai cos'è "Perm" è l'abbreviazione di [... giusto?] (Http://en.wiktionary.org/wiki/permanent#Adjective) –
La memoria allocata in Java Perm Gen può essere ancora raccolta. La JVM usa Perm Gen per conservare i dati che si aspetta siano liberati molto raramente. – mchr