Tomcat – java.lang.OutOfMemoryError: PermGen space

Often time, Tomcat may hits the following java.lang.OutOfMemoryError: PermGen space error.


java.lang.OutOfMemoryError: PermGen space
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)

It’s usually happened after the Tomcat restarts a few times.

1. Solution

By default, Tomcat is assigned a very little PermGen memory for the running process. To fix it, increase the PermGen memory settings by using the following Java VM options.


-XX:PermSize<size> - Set initial PermGen Size.
-XX:MaxPermSize<size> - Set the maximum PermGen Size.

In the next step, we will show you how to set the VM options in Tomcat, under Windows and Linux environment.

2. Windows

Tomcat is managed by this script file catalina.bat, dive inside the script, you will find out that catalina.bat always find and run the setenv.bat file to set the environment variables.

{$tomcat-folder}\bin\catalina.bat

//...
rem Get standard environment variables
if not exist "%CATALINA_BASE%\bin\setenv.bat" goto checkSetenvHome
call "%CATALINA_BASE%\bin\setenv.bat"
goto setenvDone
:checkSetenvHome
if exist "%CATALINA_HOME%\bin\setenv.bat" call "%CATALINA_HOME%\bin\setenv.bat"
:setenvDone
//...

2.1 To set the environment variable on Windows, create a setenv.bat manually, and put it into the ${tomcat-folder}\bin folder.

${tomcat-folder}\bin\setenv.bat

set JAVA_OPTS=-Dfile.encoding=UTF-8 -Xms128m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m

P.S No double quotes, set JAVA_OPTS={value}.

2.2 Restart Tomcat, it will call the setenv.bat file to set the environment variable automatically.


{$tomcat-folder}\bin\catalina.bat restart

3. Linux

On Linux, the process is same, just Tomcat is using catalina.sh and setenv.sh instead.

3.1 Find out where is catalina.sh :

catalina.sh

$ sudo find / -name "catalina.sh"
Password:
find: /dev/fd/3: Not a directory
find: /dev/fd/4: Not a directory
/Users/mkyong/Downloads/apache-tomcat-6.0.35/bin/catalina.sh

3.2 Review the catalina.sh, script, it behaves like Windows, but use setenv.sh instead.


//...
# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=

if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
  . "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
  . "$CATALINA_HOME/bin/setenv.sh"
fi
//...

3.3 Create a setenv.sh manually, and put it into the ${tomcat-folder}\bin\ folder.

${tomcat-folder}\bin\setenv.sh

export JAVA_OPTS="-Dfile.encoding=UTF-8 -Xms128m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m"

P.S With double quotes, export JAVA_OPTS=”{value}”.

3.4 Restart Tomcat.

Note
The heap size and non-heap size (perm gen) value is just an example, you should change the value accordingly to suit your project needs.

References

  1. Configure Tomcat Memory Settings
  2. Oracle : Presenting the Permanent Generation
  3. Useful JVM Flags – Part 5 (Young Generation Garbage Collection)
  4. How To Install Tomcat On Ubuntu
  5. Find Out Your Java Heap Memory Size

99 comments on “Tomcat – java.lang.OutOfMemoryError: PermGen space

  1. Can someone clarify what is meaning of Xms,Xmx, PermSize and MaxPermSize so I can configure server accordingly.

    Reply
  2. After working with applications dying with OutOfMemoryErrors for three years, I can say that adding more PermGen to application servers is 95% of the cases just masking the underlying symptoms instead of solving the actual problem.

    Most often the java.lang.OutOfMemoryError: Permgen space is triggered during redeploys when buggy code blocks classloaders from being garbage collected. There are loads of bugs in 3rd party libraries triggering it – JDBC drivers, threadpool implementations, job schedulers, you name it. There are several ways to find the offending code heap dumps, profilers or specialized tools such as https://plumbr.eu directly pinpointing you to the root cause and offering solution guidelines.

    Full disclosure: I am affiliated with Plumbr.

    Reply
    1. often true, though in case of JSF and JSP applications it isn’t always that simple as the JSP compiler itself can easily run out of permgen space in some versions when you have highly complex pages.

      Of course with the advent of Java 8 and newer, there’s no more permgen space (though you can now run out of system RAM in extreme cases).

      Reply
  3. Thank you MKyong, i spent 6 hours trying to solve this tomcat server startup problem.

    Reply
  4. how to do the same in tomact8 where catalina.sh is not availbale? Could any one respond?

    Reply
  5. Isn’t it better to use CATALINA_OPTS though? Even shutdown would use JAVA_OPTS.

    Reply
  6. There isn’t a catalina.bat in my Windows Tomcat 7 install

    Reply
  7. On windows(tomcat 7), just write: set JAVA_OPTS=-Xms128m -Xmx192m fixed the provlem

    Reply
  8. Dear MKyong, in the last 2 days i had to solve several problems with my project, and found a great part of the solutions in this site. Congratulations for maintaining such a useful place and thank you so much for sharing your knowledge.

    Reply
  9. Serious error in your instructions for catalina.bat. You can’t have the quotes when you set JAVA_OPTS=… in catalina.bat.

    Reply
    1. For windows it should be
      set JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC

      Reply
  10. Great, thanks! Worked like a charm. Before reading this post, I was going through the hundreds of lines in the catalina script to find out which variable would best fit the JVM arguments.

    Reply
  11. The above solutions (setting PermSize & MaxPermSize) sometimes don’t help while doing a hot deploy or redeploy of a web application in tomcat. I could see PermGenSpace:OutOfMemory error while doing that in my tomcat.

    Got resolved by adding -XX:+UseConcMarkSweepGC and -XX:+CMSClassUnloadingEnabled parameters to the tomcat startup script along with the other parameters. -XX:+CMSClassUnloadingEnabled parameter clears the PermgenSpace which is a non-heap memory.

    Reply
    1. Hello Ayas, I have the same problem. I try mkyong post and it help for few days. could you please help me with providing some more information how to do that. I am new with linx .

      Reply
  12. In catalina.bat file. can i simplay PAST these line or its 1st need to “SET”

    JAVA_OPTS=”-Djava.awt.headless=true -Dfile.encoding=UTF-8
    -server -Xms1536m -Xmx1536m
    -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC”

    Reply
  13. Plz , how to change the “Xms” and “PermSize” value on Apache Tomcat 7 ?

    Reply
  14. Thanks a lot.

    I was wondering is there any way to set it through a java config class for a java web application so that we just have to copy paste the war into any tomcat installations.

    Reply
  15. MYKONG if i were a girl i’d say your fine. You have saved me a dozen times.

    Reply
  16. My server has only 1024 MB Memory. What configuration do u suggest ? Am confused about 1536m !

    Reply
  17. i could not found the catalina.sh or catalina.bat file. wat should i do

    Reply
  18. Thanks a lot!!!!It’s working for my ubuntu server..

    Reply
  19. Thanks,

    But what’s the default memory size configuration in Tomcat7 ?

    Reply
  20. Bravo !!! Works for me . Thank you very much!!!

    Reply
  21. 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.

    Reply
    1. That was useful for me. Thanks Nitin.
      Thanks MKYong

      Reply
  22. Excellent!

    Thank you very much!

    My two cents is that I had to apply JAVA_OPTS with setenv.sh script into CATALINA_BASE/bin:

    JAVA_OPTS=”-Djava.awt.headless=true -Dfile.encoding=UTF-8
    -server -Xms1536m -Xmx1536m
    -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC”

    it is working!

    Reply
  23. It is just perm gen error! Why are you changing java.awt.headless, file.encoding and java heap size? This arguments is de trop.

    Reply
  24. Hello, thanks for sharing solutions. Your blog saved lots of time for me.

    There is strange thing in your example:
    “-Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m”
    1) memory heap size for new objects limited by 256Mb
    2) memory heap size for permanent objects limited by 256Mb
    So we have 500Mb reserved for objects. And it’s not clear how rest 1000Mb will be used?

    Reply
  25. Thanks for the solution. It may great for the Tomcat family with who want to learn.

    Reply
  26. Thanks!
    I was struggling with this error from last week. This article clearly explains why this error is coming and how to avoid it. I will try suggested solution. Hope this error will get fixed.

    Reply
  27. Above thing does not work when you use tomcat with eclipse “(

    Reply
  28. Oh, and you should create a file “setenv.sh” rather than messing with catalina.sh

    Reply
  29. You should use CATALINA_OPTS instead of JAVA_OPTS to set your heap size – because JAVA_OPTS is also used when you call “stop” – and it’s unlikely you need a huge heap to just shut down the app.

    Reply
  30. This issue is far more complicated than your article acknowledges. For some people, they do not have a PermGen memory leak and simply have more classes to load into PermGen than their memory settings allow, and your solution works correctly (and is a true solution) for them.

    However, for many people, they are getting PermGen errors because they have an actual PermGen memory leak (yes, it’s possible in Java, just not in quite the same way as in C++) that becomes apparent following a hot re-deploy, and your solution will delay, BUT NOT PREVENT their problem. In those situations, the memory leak occurs because classes loaded by the webapp’s classloader are referenced by some object loaded in a different classloader, and so cannot be garbage-collected after the webapp is undeployed/reloaded, or because their webapp leaves one or more threads running when it is stopped. A very good explanation of the problem can be found here: http://blogs.oracle.com/fkieviet/entry/classloader_leaks_the_dreaded_java

    For people with this kind of memory leak, your configuration settings will make it look like the problem has been fixed (for a while), and then after a certain number of hot re-deploys, it will occur again. So they’ll leave your blog thinking you’re the man for solving their problems (they do, from the comments), only to discover later that your solution didn’t actually work, and they’ll no longer think so highly of you. So you should probably modify the post to include more nuance in your explanation, so people don’t think badly of you for giving them information that turned out not to be right…

    Reply
    1. Thanks for sharing your invaluable comment and also the Oracle link.

      To be frankly, i don’t mind how people think of me, and believe people should learn through sharing, and your provided Oracle classloader leaks link is really useful.

      Reply
      1. SEVERE: Exception invoking method check
        java.lang.OutOfMemoryError: PermGen space
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
        at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2818)
        at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
        at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2818)
        at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:247)

        Reply
  31. can you please edit the article and describe the parameters and what every parameter does, so people don’t just copy paste and understand what’s going on.

    Reply
    1. and also how to check that the memory increased already on windows or linux ?

      Reply
  32. I have “Error occurred during initialization of VM
    Too small initial heap for new size specified”

    What’s it that?

    Reply
  33. Got to start->All programs->Apache TomCat->Configure Tomcat in that select Java Tab there you get java options change the java settings.

    Reply
  34. Please help I added the above line i get this error while calling ./ahutdown.sh
    Exception in thread “main” java.lang.NoClassDefFoundError: $/-Djava/awt/headless=true
    Please reply thanks

    Reply
  35. uhmmmm, that’s great, but how can i do this in windows tomcat.
    There is no catalina.sh file, just tomcat5.exe, dll, and jar files.

    There is a Configure.. option in tomcat monitor, but I’m not sure how to configure this options.

    Reply
    1. Not familiar with the Window version, cant find the Java options in the “conf” folder as well.

      But you can run the “tomcat6w.exe”, click on the “Java” tab, and configure the value in the Java Options field.

      Reply
    2. add in the bin\startup.bat file
      SET JAVA_OPTS=”-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC”

      Reply
  36. thank you… uffffffff.. many hours searching the solution

    Reply
  37. you should not edit your catalina.sh file to shove these things in there – you should instead create a

    “setenv.sh” file that catalina calls when it runs and put the export JAVA_OPTS=” ” line in that setenv.sh file.

    Reply
      1. Hi..

        Thanks for posting lot of useful info. Appreciate your effort.

        Could you please explain (may be on a seperate thread) what each of these mean

        1. what is permgen space
        2.what is new space
        3.how chnage the command options is helping us resolve the isssue.

        Thanks in Advance

        Regards,
        Maddy

        Reply

Leave a Comment

Your email address will not be published. Required fields are marked *