Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does the perm gen get collected?

I work on a Tomcat application which uses the CMS collector along with a memory bar to trigger GC. When I reload webapps I sometimes end up in a situation where the Old gen is full enough to trigger GC but the dead Classloaders don't get collected.

I read that Classes are allocated into the perm gen and guessed that they were therefore being ignored by the Old gen collections. I wrote the following test class to test this theory.

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];
}

I ran this class and monitored the output using VisualVM and saw that there were indeed multiple Old and Young gen collections happening without the dead Classloader being collected and therefore the large byte array remained in memory.

VisualVM Visual GC

What would trigger the Perm Gen to be collected?

like image 814
mchr Avatar asked Nov 05 '11 00:11

mchr


People also ask

Which generation is collected quickly during GC in the Hotspot JVM?

Young Generation. Most newly allocated objects are allocated in the young generation (see Figure 1), which is typically small and collected frequently.

Does garbage collection occur in permanent generation space in JVM?

When objects are garbage collected from the Old Generation, it is a major garbage collection event. Permanent Generation: Metadata such as classes and methods are stored in the Permanent Generation. Classes that are no longer in use may be garbage collected from the Permanent Generation.

What is perm gen space in heap?

A java. lang. OutOfMemoryError: PermGen Space is a runtime error in Java which occurs when the permanent generation (PermGen) area in memory is exhausted. The PermGen area of the Java heap is used to store metadata such as class declarations, methods and object arrays.

Why does java 8 remove PermGen space?

The main reason for removing PermGen in Java 8 is: It is very hard to predict the required size of PermGen. It is fixed size at startup, so difficult to tune. Future improvements were limited by PermGen space.


1 Answers

Check out JVM options "CMSPermGenSweepingEnabled" and "CMSClassUnloadingEnabled". (There are plenty of discussions on the net re their use.) In particular, the first one suppose to include the PermGen in a garbage collection run. By default, the PermGen space is never included in garbage collection (and thus grows without bounds).

like image 172
mazaneicha Avatar answered Sep 27 '22 23:09

mazaneicha