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.
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.
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:
Here are some of the common causes of java.lang.OutOfMemoryError: PermGen space in tomcat server:
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 Catalina.sh 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 Catalina.sh
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.
Related Java Tutorials
Why people so much afraid of java.lang.OutOfMemoryError in Tomcat, Eclipse or whatsoever ?
ReplyDeletethis is a gud explanation and we also had this error driving us mad recently...
ReplyDeleteYou 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.
ReplyDeleteYou 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.
ReplyDeleteYou 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.
ReplyDeleteTo 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.
ReplyDeleteThere is a better way to proof the consumed memory of the Tomcat server process on java.lang.OutOfMemoryError, see here http://technohandle.blogspot.de/2012/05/using-visualvm-profiler-in-tomcat.html
ReplyDeleteYou have a mistake in your setup of JVM options (maximum JVM heap size) "-Xmx10246m" is to much memory.
ReplyDeleteThat could be correct, when it exists 16g RAM on the used computer system.
Note: ms-windows should be running on 64 bit system.
I am getting java.lang.OutOfMemoryError PermGen Space in Jetty Server, does any one has experience with Jetty here ?
ReplyDeletefrom 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
ReplyDeletejava.lang.OutOfMemoryError: Metaspace
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.
ReplyDelete@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 :)
ReplyDeleteThe -Xmx10246m variable should be -Xmx1024m. There is a '6' that should not be there.
ReplyDeletehello javin,
ReplyDeletei 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.
Worked for me as is, inside and outside eclipse with Tomcat 7.
ReplyDeleteMany thanks
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.
ReplyDeleteHello, I am getting following error on Tomcat Server's catalina.out file :
ReplyDeleteSEVERE: 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.
and
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.
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
ReplyDeletehow add JAVA_OPTS please give me solution . it's very important
ReplyDelete