Dealing with "java.lang.OutOfMemoryError: PermGen space" error

1,052,121

Solution 1

The solution was to add these flags to JVM command line when Tomcat is started:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

You can do that by shutting down the tomcat service, then going into the Tomcat/bin directory and running tomcat6w.exe. Under the "Java" tab, add the arguments to the "Java Options" box. Click "OK" and then restart the service.

If you get an error the specified service does not exist as an installed service you should run:

tomcat6w //ES//servicename

where servicename is the name of the server as viewed in services.msc

Source: orx's comment on Eric's Agile Answers.

Solution 2

You better try -XX:MaxPermSize=128M rather than -XX:MaxPermGen=128M.

I can not tell the precise use of this memory pool, but it have to do with the number of classes loaded into the JVM. (Thus enabling class unloading for tomcat can resolve the problem.) If your applications generates and compiles classes on the run it is more likely to need a memory pool bigger than the default.

Solution 3

App server PermGen errors that happen after multiple deployments are most likely caused by references held by the container into your old apps' classloaders. For example, using a custom log level class will cause references to be held by the app server's classloader. You can detect these inter-classloader leaks by using modern (JDK6+) JVM analysis tools such as jmap and jhat to look at which classes continue to be held in your app, and redesigning or eliminating their use. Usual suspects are databases, loggers, and other base-framework-level libraries.

See Classloader leaks: the dreaded "java.lang.OutOfMemoryError: PermGen space" exception, and especially its followup post.

Solution 4

Common mistakes people make is thinking that heap space and permgen space are same, which is not at all true. You could have lot of space remaining in the heap but still can run out of memory in permgen.

Common causes of OutofMemory in PermGen is ClassLoader. Whenever a class is loaded into JVM, all its meta data, along with Classloader, is kept on PermGen area and they will be garbage collected when the Classloader which loaded them is ready for garbage collection. In Case Classloader has a memory leak than all classes loaded by it will remain in memory and cause permGen outofmemory once you repeat it a couple of times. The classical example is Java.lang.OutOfMemoryError:PermGen Space in Tomcat.

Now there are two ways to solve this:
1. Find the cause of Memory Leak or if there is any memory leak.
2. Increase size of PermGen Space by using JVM param -XX:MaxPermSize and -XX:PermSize.

You can also check 2 Solution of Java.lang.OutOfMemoryError in Java for more details.

Solution 5

Use the command line parameter -XX:MaxPermSize=128m for a Sun JVM (obviously substituting 128 for whatever size you need).

Share:
1,052,121
Chris
Author by

Chris

My languages, ordered by fluency: English, SQL, Ruby, Java, Mandarin Chinese, Python, Javascript, HTML, CSS.

Updated on March 14, 2022

Comments

  • Chris
    Chris about 2 years

    Recently I ran into this error in my web application:

    java.lang.OutOfMemoryError: PermGen space

    It's a typical Hibernate/JPA + IceFaces/JSF application running on Tomcat 6 and JDK 1.6. Apparently this can occur after redeploying an application a few times.

    What causes it and what can be done to avoid it? How do I fix the problem?

    • Eran Medan
      Eran Medan over 14 years
      I have fought this for hours, but I have no good news. See my related question: stackoverflow.com/questions/1996088/… You may still have a memory leak, e.g. classes are not garbage collected because your WebAppClassLoader is not garbage collected (it has an external reference that is not cleared). increasing the PermGen will only delay the OutOfMemoryError, and allowing class garbage collection is a precondition, but will not garbage collect classes if their class loader still has references to it.
    • masT
      masT over 10 years
      I got this error at adding display taglib. Removing so also solved the error. Why so?
    • matbrgz
      matbrgz about 10 years
      And how did you run into it?
    • Rytek
      Rytek about 10 years
      use JDK 1.8 :þ welcome to the MetaSpace
    • MacGyver
      MacGyver about 7 years
      If using Windows, follow these instructions instead of trying to set the flags manually in the config files. This properly sets the values in the registry to be called by Tomcat during runtime. stackoverflow.com/questions/21104340/…
  • meerkatlookout
    meerkatlookout over 15 years
    The only issue is that you're just delaying the inevitable- at some point you'll run out of headroom there too. It's a great pragmatic solution, but it doesn't solve it permanently.
  • Matt
    Matt over 15 years
    same thing occurs in Eclipse and any time you have lots of dynamic class loading. the classloaders aren't disposed of and live in the permanent generation for all eternity
  • Taylor Leese
    Taylor Leese almost 15 years
    The article below suggests -XX:+UseConcMarkSweepGC and -XX:MaxPermSize=128m as well. my.opera.com/karmazilla/blog/2007/03/13/…
  • Eldelshell
    Eldelshell over 13 years
    -XX:+CMSPermGenSweepingEnabled This option brings down performance. It makes each request take three times more time than usual on our systems. Use with care.
  • sami
    sami over 13 years
    worked for me - thanks - I am doing this on Ubuntu 10.10 with Tomcat6 - I created a new file: /usr/share/tomcat6/bin/setenv.sh and added the following line to that: JAVA_OPTS="-Xms256m -Xmx512m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled" - Restarted tomcat using: sudo /etc/init.d/tomcat6 start
  • knb
    knb almost 13 years
    On tomcat 6.0.29 startup, from my catalina.out logfile: "Please use CMSClassUnloadingEnabled in place of CMSPermGenSweepingEnabled in the future"
  • stivlo
    stivlo almost 13 years
    On a tomcat 5.5 on Ubuntu I've changed /etc/default/tomcat5.5 with the following JAVA_OPTS="-Djava.awt.headless=true -Xms128M -Xmx512M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=128m"
  • Dave
    Dave over 12 years
    I was running out of PermGen when executing a particularly large Hudson job...this fixed it for me.
  • Péter Török
    Péter Török over 12 years
    @TimHowland, it can be a permanent fix if the root cause is not classloader leakage, just too many classes/static data in your web app.
  • Deckard
    Deckard over 12 years
    How to pass param -XX:MaxPermSize and -XX:PermSize?? I can't find catalina.bat. My tomcat version is 5.5.26.
  • false9striker
    false9striker about 12 years
    I'm not able to open up tomcat6w.exe :( It says "The specified service does not exist as an installed service. Unable to open the service 'tomcat6' " . Could anyone help me on this?
  • Alex
    Alex almost 12 years
    "argLine" is not recognized by maven-compiler-plugin 2.4. it only supports "compilerArgument", which gives error: <compilerArgument>-XX:MaxPermSize=256m</compilerArgument> [ERROR] Failure executing javac, but could not parse the error: javac: invalid flag: -XX:MaxPermSize=256m Usage: javac <options> <source files>
  • Rade_303
    Rade_303 almost 12 years
    This is only true solution to the problem, ableit in some cases too hard to implement.
  • Rade_303
    Rade_303 almost 12 years
    Actually, this will only postpone OOMError. See answer below started by anon with two links to frankkieviet blog.
  • Nikem
    Nikem almost 12 years
    First of all it would be great to explain what these flags really do. Just saying: "do that and enjoy" is not enough IMHO.
  • Nikem
    Nikem almost 12 years
    And second, if your application really leaks class loader, meaning that it leaves somewhere some object or class loaded by application's class loader even after undeployment, then these flags will not help. I have written blog post about this and other suggestions in this topic: plumbr.eu/blog/busting-permgen-myths
  • stracktracer
    stracktracer almost 12 years
    While JRockit indeed has no PermGen, but this will not help in the long run. You'll get java.lang.OutOfMemoryError: There is insufficient native memory instead.
  • gavenkoa
    gavenkoa over 11 years
    Another very good source is people.apache.org/~markt/presentations/… (from Tomcat release manager!!).
  • Joachim Sauer
    Joachim Sauer about 11 years
    Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
  • igo
    igo about 11 years
    and if it still persist try XX:MaxPermSize=1024m :)
  • Marko Vranjkovic
    Marko Vranjkovic almost 11 years
    -XX:+CMSClassUnloadingEnabled and -XX:+CMSPermGenSweepingEnabled are unusable in java 1.7, see link
  • Thomas
    Thomas almost 11 years
    and if it still persist try XX:MaxPermSize=2048m :)
  • Abdull
    Abdull over 10 years
    @lolotron, With Java OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)... running java -XX:+PrintFlagsFinal -version... the returned list of flags includes CMSClassUnloadingEnabled.
  • qwerty
    qwerty about 10 years
    If your compilation phase is running out of permgen set the <compilerArgument> on the maven-compiler-plugin. If the unit tests are running out of permgen set <argLine> in the maven-surefire-plugin
  • amos
    amos about 10 years
    These options are explained here: oracle.com/technetwork/java/javase/tech/…
  • louisgab
    louisgab about 10 years
    got the same issue as HDave when building jenkins/hudson from source.
  • Scot
    Scot almost 10 years
    If you don't want to include the driver in jre/lib/ext, you could probably get the same results by including the driver in your container startup classpath. java -cp /path/to/jdbc-mysql-driver.jar:/path/to/container/bootstrap.‌​jar container.Start
  • reallynice
    reallynice almost 10 years
    @lolotron vulgarly trying to set it on tomcat 7 on "Java HotSpot(TM) Server VM (build 24.45-b08, mixed mode)", it works fine (no more OutOfMemory errors).
  • bluish
    bluish almost 10 years
    Hello, this answer has already been given: stackoverflow.com/a/22897121/505893. Please delete your answer, for clarity. If needed you could improve the answer I mentioned. Thanks ;)
  • Edwin Buck
    Edwin Buck almost 10 years
    @bluish Thank you for pointing that out; however, that answer goes all sideways on talking about OutOfMemoryExceptions and leaking metadata. It also fails to mention the very important points of removing the PermGen option. In short, I'm not sure I would be improving the answer, but rather rewriting it. If it was just a quick touch-up, I would feel less hesitant, but it looks like it would be much more than a quick touch-up, and I'd hate to offend the original author. Still, this answer list is a dog's dinner of a mess, and perhaps killing my post would be best anyway.
  • Amit
    Amit over 9 years
    How to find the memory leaks of class loader ? Do you recommend any tool ?
  • Jonathan Airey
    Jonathan Airey over 9 years
    And if it STILL persists, rethink your application!! Or try XX:MaxPermSize=4096m :)
  • Jacek Pietal
    Jacek Pietal over 9 years
    you can also try 8192m but thats a bit of overkill
  • leomeurer
    leomeurer over 9 years
    Great post of @faisalbhagat faisalbhagat.blogspot.com/2014/09/…
  • Senthil Kumar
    Senthil Kumar over 9 years
    To know more about the flags - stackoverflow.com/questions/3334911/…
  • Joel Purra
    Joel Purra about 9 years
    Overkill indeed -- 640KB ought to be enough for anybody!
  • hdost
    hdost about 9 years
    Option 2 is great, but just be warned that it should not be used in production environments. Typically best to keep it to development environments only. However PermGen is removed as of Java 8 openjdk.java.net/jeps/122
  • Barett
    Barett about 9 years
    @amit for tool recommendations, see the community wiki answer on this question.
  • J Slick
    J Slick over 8 years
    A bit dated, like this thread, but here's documentation from Oracle: oracle.com/technetwork/java/…
  • Alex
    Alex over 8 years
    I can do this on tomcat 7: add this line to setenv.sh [JAVA_OPTS="-Xms256m -Xmx512m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled" ] ? will this work?
  • Kai Carver
    Kai Carver about 8 years
    what worked for me on windows: created file ${tomcat-folder}\bin\setenv.bat containing one line: set JAVA_OPTS=-Dfile.encoding=UTF-8 -Xms128m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m
  • Alejandro Pablo Tkachuk
    Alejandro Pablo Tkachuk about 8 years
    The correct solution is to address the memory leak problems and resolve them. If you registered JDBC Drivers, unregister them. You can use a javax.servlet.ServletContextListener. I have posted a solution below with a sample code to unregister drivers / threads / etc.
  • Zeb
    Zeb over 7 years
    @Deckard going into the Tomcat/bin directory and running tomcat6w.exe. Under the "Java" tab, add the arguments to the "Java Options" box. Click "OK"
  • gzmask
    gzmask over 7 years
    let's see... 2012 ppl say 1024, 2013 is 2048, 2014 it was 4096 and 2015 arrives at 8192. Now just spend that $100 for your 16384.
  • Chris Sim
    Chris Sim about 7 years
    Thank you for your best detailed answer (Note : click "Open launch configuration" to open "edit configuration" window... but I used the following parameters: "-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
  • LucaP
    LucaP almost 7 years
    What if I'm running a WebLogic?
  • Rostislav V
    Rostislav V almost 7 years
    Note that CMSClassUnloadingEnabled is enabled by default
  • jonasespelita
    jonasespelita almost 6 years
    Any reason why these aren't enabled by default?
  • Edward Torbett
    Edward Torbett over 4 years
    I know it's been over 8 years since I wrote this, but somewhere between then and now I found a deeper root cause and solution. This was that while all of the classes within the webapp are owned by the context classloader, the thread that invokes the startup and shutdown callback is owned by the parent classloader. This means that if the shutdown code initialises a thread-local variable, this will cause the parent classloader to end up holding a reference to the context classloader, preventing good cleanup.
  • Edward Torbett
    Edward Torbett over 4 years
    Luckily, there's a very simple fix - move all code currently in the shutdown method into a new Thread object's run method. Then in the shutdown method, start this thread and wait for it to complete. The cleanup code will be executed identically, but any thread-local variables will remain bound to the context classloader instead of leaking.
  • lpkej
    lpkej about 4 years
    Well I had same issue, so all I did is XX:MaxPermSize=131072m :)
  • srk
    srk over 2 years
    MetaSpace also can go OutOfMemory