Fully featured low overhead profiler for Java EE and Java SE platforms.
Monitoring and profiling solution for Gradle, Maven, Ant, JUnit and TestNG.
Easy to use performance and memory profiler for .NET framework.

YourKit Java Profiler solving 'java.lang.OutOfMemoryError: PermGen space' error

Can't find your answer? Please refer to documentation and demos, ask your question in forum, or contact support.

The following article is dedicated to the solution of a "java.lang.OutOfMemoryError: PermGen space" error. This problem is both common and widespread, and in the same time doesn't have a simple solution due to its specific character. For sure, finding PermGen leaks is well-known for many specialists who write Java web-applications and have to redeploy them many times.

Of course, there are some tools, such as standard JDK jmap (Memory Map) and jhat (Heap Analysis Tool), used to somehow deal with finding PermGen leaks, though none of them could be referred to as easy and effective.

Here we will show YourKit Java Profiler with its new "Class loaders" feature in order to confirm that the aforementioned problem may be now easily solved.

Consider a simple example of a web-application on Tomcat server. We will demonstrate several steps which should be done to hunt down the "java.lang.OutOfMemoryError: PermGen space" error with the help of YourKit Java Profiler.

Step 1. Enable profiling

Step 2. Load up, use and undeploy your application in the way you usually do it.

Step 3. Use toolbar button to capture a memory snapshot. Then open the obtained snapshot to start analysis.

Step 4. Now it's right time to examine "Class loaders" view. As far as finding PermGen memory leaks is the case, we should first of all focus on classes without instances. And that is exactly what "Class loaders" view shows us in "Classes w/o instances" column. We can now easily identify classes which belong to our profiled application and may cause the leak. This may be known by large or increasing number of the class instances.


As we see, there is org.apache.catalina.loader.WebappClassLoader which has 5 classes and 4 without instances among them. These classes definitely belong to our profiled application, though the application itself has been already undeployed.

Step 5. After we have identified classes without instances it should be found out why org.apache.catalina.loader.WebappClassLoader is still present. At this point, we will use "Paths to Loader" tab, which shows the consecutive chain of objects referencing each other and leading to the loader which we are interested in.


After studying paths, we can say why org.apache.catalina.loader.WebappClassLoader has not been collected. It is a loader of com.yourkit.AccessTime class with the instance stored in ThreadLocalMap of thread "http-8080-3".

And now let's take a look into the corresponding source code fragment of the profiled application:



public class AccessUtil {
  private static ThreadLocal<AccessTime> threadLocal = new ThreadLocal<AccessTime>();

  public static Date getLastAccessTime(){
    final AccessTime accessTime = threadLocal.get();

    threadLocal.set(new AccessTime());

    return accessTime != null? accessTime.value : new Date();
  }
}

final class AccessTime {
  public Date value = new Date();

  public AccessTime() {
    new Class1();
  }
}

final class Class1{
  public Class1() {
    new Class2();
  }
}

final class Class2{
  public Class2() {
    new Class3();
  }
}

final class Class3{

}