Sunday, January 1, 2017

Tomcat – java.lang.OutOfMemoryError: PermGen space Cause and Solution

Tomcat web server often suffers from java.lang.OutOfMemoryError: PermGen space whenever you deploy and un-deploy your web application a couple of times. No matter you are using tomcat6, tomcat7, or using bundled tomcat in Netbeans or Eclipse you will face this error now and then while developing web application on tomcat server. I thought about this article after writing 2 Solution of OutOfMemoryError in Java. I have touched this issue there but then I thought to write a separate tutorial for tomcat outofmemoryerror because I am getting this error too frequently.

In this article, we will see what causes java.lang.OutOfMemoryError: PermGen Space in tomcat and how to fix java.lang.OutOfMemoryError: PermGen Space in the tomcat server.

Btw, if you are new into Servlet and JSP then I also suggest you go through a comprehensive course to learn Servlet and JSP in depth. If you need a recommendations then I suggest you check out JSP, Servlet, and JDBC for Beginners: Build a Database App course on Udemy by Chad Darby. One of the hands-on course to learn Servlet and JSP. 

Tomcat – java.lang.OutOfMemoryError: PermGen space Cause and Solution

1. Cause of OutOfMemoryError in PermGen space in Tomcat:

PermGen Space of the heap is used to store classes and Metadata about classes in Java. When a class is loaded by a classloader it got stored in PermGen space, it gets unloaded only when the classloader which loaded this class got garbage collected. If any object retains reference of classloader than it's not garbage collected and Perm Gen Space is not freed up. 

This causes a memory leak in PermGen Space and eventually causes java.lang.OutOfMemoryError: PermGen space. Another important point is that when you deploy your web application a new Classloader gets created and it loads the classes used by the web application. So if Classloader doesn't get garbage collected when your web application stops you will have a memory leak in tomcat.

Solution of Tomcat: OutOfMemroyError:

1) Find the offending classes which are retaining reference of Classloader and preventing it from being garbage collected. Tomcat provides memory leak detection functionality after tomcat 6 onwards which can help you to find when the particular library, framework or class is causing a memory leak in tomcat. 

Here are some of the common causes of java.lang.OutOfMemoryError: PermGen space in tomcat server:

tomcat java.lang.outofmemoryerror:permgen space solution1) JDBC Drivers:
JDBC drivers are the most common cause of java.lang.OutOfMemoryError: PermGen space in tomcat if the web app doesn't unregister during the stop. One hack to get around this problem is that JDBC driver to be loaded by a common classloader than application classloader and you can do this by transferring driver's jar into tomcat lib instead of bundling it on the web application's war file.

2) Logging framework:
A similar solution can be applied to prevent logging libraries like Log4j causing java.lang.OutOfMemoryError: PermGen space in tomcat.

3) Application Threads that have not stopped.
Check your code carefully if you are leaving your thread unattended and running in a while loop that can retain the classloader's reference and cause java.lang.OutOfMemoryError: PermGen space in the tomcat web server. Another common culprit is ThreadLocal, avoid using it until you need it absolutely, if do you make sure to set them null or free any object ThreadLocal variables are holding.

Another Simple Solution is to increase PermGen heap size in catalina.bat or of tomcat server; this can give you some breathing space but eventually, this will also return in java.lang.OutOfMemoryError: PermGen space after some time.

Steps to increase PermGen Heap Space in Tomcat:

1) Go to Tomcat installation directory i.e C:\Program Files\Apache Software Foundation\Apache Tomcat 7.0.14\bin in Windows and something similar in Linux.

2) Add JAVA_OPTS in your catalina.bat or

In Windows:

set JAVA_OPTS="-Xms1024m -Xmx10246m -XX:NewSize=256m -XX:MaxNewSize=356m -XX:PermSize=256m -XX:MaxPermSize=356m"

In linux:

export JAVA_OPTS="-Xms1024m -Xmx10246m -XX:NewSize=256m -XX:MaxNewSize=356m -XX:PermSize=256m -XX:MaxPermSize=356m"

You can change the actual heap size and PermGen Space as per your requirement.

3) Restart Tomcat.

As I said earlier increasing PermGen space can prevent java.lang.OutOfMemoryError: PermGen in tomcat only for some time and it will eventually occur based on how many times you redeploy your web application, its best to find the offending class which is causing a memory leak in tomcat and fix it.

Further Learning
Java Web Fundamentals By Kevin Jones
Spring Framework 5: Beginner to Guru
JSP, Servlets and JDBC for Beginners: Build a Database App

Related Java Tutorials


Anonymous said...

Why people so much afraid of java.lang.OutOfMemoryError in Tomcat, Eclipse or whatsoever ?

hemant said...

this is a gud explanation and we also had this error driving us mad recently...

Anonymous said...

You shouldn't include JDBC driver in your classpath because its better to use Database Connection pool provided by J2EE Server or Tomcat instead of Managing JDBC Pool on code. This not only removes dependency like JDBC driver, DBCP or any other jar but also get rid of this OutOfMemroy Error in Tomcat by effectively shifting driver jar into tomcat lib folder.

Anonymous said...

You are correct I have faced java.lang.OutOfMemoryError: PermGen space on both Tomcact 6 and Tomcat 7. though tomcat print useful information like whether its ThreadLocal which is causing OutOfMemory etc but for permgen space you need to do this analysis. the step we have taken is to increase PermGen and stop frequent redeploy of webapp without restarting server.

Sanju said...

You are correct I have faced java.lang.OutOfMemoryError: PermGen space on both Tomcact 6 and Tomcat 7. though tomcat print useful information like whether its ThreadLocal which is causing OutOfMemory etc but for permgen space you need to do this analysis. the step we have taken is to increase PermGen and stop frequent redeploy of webapp without restarting server.

Memory leak detector said...

To find the "offending class which is causing memory leak in tomcat", use Plumbr. It gives you the details of the leak, and also teaches how to solve the leak in-process.

Unknown said...

There is a better way to proof the consumed memory of the Tomcat server process on java.lang.OutOfMemoryError, see here

Unknown said...

You have a mistake in your setup of JVM options (maximum JVM heap size) "-Xmx10246m" is to much memory.

That could be correct, when it exists 16g RAM on the used computer system.
Note: ms-windows should be running on 64 bit system.

Anonymous said...

I am getting java.lang.OutOfMemoryError PermGen Space in Jetty Server, does any one has experience with Jetty here ?

Anonymous said...

from Java 8, Oracle is removing PermGen space from JVM, which means no java.lang.OutOfMemoryError: PermGen space, instead they are introducing metaspace which will give berth to a new set of OutOfMemoryError in Java

java.lang.OutOfMemoryError: Metaspace

coding_idiot said...

For all those who use the installer version of tomcat. You can set it(java_opts) through running tomcat6w.exe (configuration manager) and under the java tab, in the java/jvm options textbox.

Steward said...

@Anonymous is right, Java 1.8 has no PermGen Space, means, you don't need to worry about outofmemory error in permgen space, but question is how many organization will use Java 1.8, I think Java 1.6 is still most popular JDK out there, programmers and companies have not adopted Java 7 till date, it will take another five years, before Industry start using Java 1.8, till then keep debugging permgen memory leak :)

Anonymous said...

The -Xmx10246m variable should be -Xmx1024m. There is a '6' that should not be there.

Anonymous said...

hello javin,
i have a question.At the time of undeploy that application what happens exactly ? is it free the reserved space or not. can you please give the answer.

Abu al-Sous said...

Worked for me as is, inside and outside eclipse with Tomcat 7.

Many thanks

Anonymous said...

Great article Javin, Though I agree that JDBC drivers especially MySQL JDBC Drivers cause some classloader memory leak in tomcat, I am not fully agree with solution of putting JDBC drivers on Tomcat lib. MySQL JDBC driver has some bug in there earlier versions, prior to 5.1.23, which creates threads for cleaning up abandoned connection, but that outlive web application. A better solution to fix java.lang.OutOfMemoryError: PermGen Space due to memory leak caused by JDBC drivers or Threads in general is stopping them during Application redeploy. One way of doing this in web application is by adding ServletContextListener, which defines contextDestroyed(ServletContext ctx) method. This method is called during undeploy, stopping any cleanup thread e.g. MySQL abandoned connection cleanup thread, can prevent this classloader memory leak. This is the general approach for fixing memory leak, but in particular cases, like in this case you can simply upgrade MySQL JDBC Driver to version 5.1.23 or above.

Anonymous said...

Hello, I am getting following error on Tomcat Server's catalina.out file :

SEVERE: The web application registered the JDBC driver [oracle.jdbc.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application appears to have started a thread named [Thread-10] but has failed to stop it. This is very likely to create a memory leak.


SEVERE: The web application created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@64b43\712c]) and a v
alue of type [org.apache.logging.log4j.core.async.AsyncLogger.Info] (value [org.apache.logging.log4j.core.async.AsyncLogger$Info@3404e643e]) but failed
to remove it when the web application was stopped. This is very likely to create a memory leak.

Any idea how to resolve these error and prevent them from coming again? I am using Tomcat 6 installations.

Anonymous said...

As per your suggestion, I have moved my driver JAR to tomcat's lib directly but now my application is not starting any more, I always getting HTTP 404 error, whenever I access my application, please help

Unknown said...

how add JAVA_OPTS please give me solution . it's very important

Post a Comment