tags:

views:

1870

answers:

6

I'm running Tomcat6 in Sun's JRE6 and every couple deploys I get OutOfMemoryException: PermGen. I've done the Googling of PermGen solutions and tried many fixes. None work. I read a lot of good things about Oracle's JRockit and how its PermGen allocation can be gigs in size (compare to Sun's 128M) and while it doesn't solve the problem, it would allow me to redeploy 100 times between PermGen exceptions compared to 2 times now.

The problem with JRockit is to use it in production you need to buy WebLogic which costs thousands of dollars. What other (free) options exist that are more forgiving of PermGen expansion? How do the below JVMs do in this area?

  • IBM JVM
  • Open JDK
  • Blackdown
  • Kaffe

...others?

Update: Some people have asked why I thought PermGen max was 128M. The reason is because any time I try to raise it above 128M my JVM fails to initialize:

[2009-06-18 01:39:44] [info] Error occurred during initialization of VM [2009-06-18 01:39:44] [info] Could not reserve enough space for object heap [2009-06-18 01:39:44] [395 javajni.c] [error] CreateJavaVM Failed

It's strange that it fails trying to reserve space for the object heap, though I'm not sure it's "the" heap instead of "a" heap.

I boot the JVM with 1024MB initial and 1536MB max heap.

I will close this question since it has been answered, ie. "switching is useless" and ask instead Why does my Sun JVM fail with larger PermGen settings?

+4  A: 

What gave you the idea that Sun's JVM is restricted to 128M PermGen? You can set it freely with the -XX:MaxPermSize command line option; the default is 64M.

However, the real cause of your problem is probably a memory leak in your application that prevents the classes from getting garbage collected; these can be very subtle, especially when ClassLoaders are involved, since all it takes is a single reference to any of the classes, anywhere. This article describes the problem in detail, and this one suggests ways to fix it.

Michael Borgwardt
I have read that article, but it doesn't provide anything practically useful on something that isn't some stupid little micro-example. OP just needs to get used to it and not waste time trying to fix it.
GreenieMeanie
Either you have not read the second article, or you have not understood it.
Michael Borgwardt
Class loaders really aren't that hard... yet people seem to be greatly intimidated by them.
CurtainDog
+2  A: 

Technically, the "PermGen" memory pool is a Sun JVM thing. Other JVMs don't call it that, but they all have the idea of one or more non-heap memory pools.

But if you have a problem with permgen in your Sun JVM, moving to another JVM is very unlikely solve anything, it'll just manifest itself under a different name.

If multiple redeployments are causing your problems, just boost the VM's PermGen up to large values. We tried JRockit a while back because of this very problem, and it suffers from the same redeployment exhaustion. We moved back to SUn JVM.

skaffman
Thanks, that's the experience I'm looking for. I originally looked at JRockit because people were claiming you could increase its PermGen equivalent to gigabytes, at least allowing for longer times spans between blowing up.
rcampbell
A: 

I use JRockit and I still get PermGen errors if I don't bump up (via -XX:MaxPermSize) the memory. I also can't get anything to work to avoid getting this (other than increasing it).

GreenieMeanie
JRockit doesn't have a permspace, so I don't understand how it can get any better if you bump it up with -XX:MaxPermSize? If you run JRockit with -XX:MaxPermSize you'll get this warning message:[WARN ] -XX:MaxPermSize is not a valid VM option. IgnoringDid you really run your application with JRockit?
Kire Haglin
+6  A: 

I agree with Michael Borgwardt in that you can increase the PermGen size, I disagree that it's primarily due to memory leaks. PermGen space gets eaten up aggressively by applications which implement heavy use of Reflection. So basically if you have a Spring/Hibernate application running in Tomcat, be prepared to bump that PermGen space up a lot.

ThaDon
Exactly. Traditional memory leaks can't happen due to GC, but PermGen is not typically GC at all. I use both Spring and Hibernate which both make heavy use of reflection.
rcampbell
I don't think this is true. I don't see why just using reflection would require memory to be allocated in PermGen but I will go off and test it. Spring and Hibernate make heavy use of proxies but you should see this settle down. Likewise Tomcat will use up PermGen when compiling JSPs but again this should still settle down after a bit (useless you have something like Always Compile JSPs turned on). In any case anecdotal evidence suggests that it is possible to run a full j2ee stack on sun's jvm without it tanking...
CurtainDog
+2  A: 

Changing JVM is not a panacea. You can get new unexpected issues (e.g. see an article about launching an application under 4 different JVM).

  • You can have a class leak (e.g. via classloaders) that mostly often happen on redeploy. Frankly, I've never saw working hot redeploy on Tomcat (hope to see one day).
  • You can have incorrect JVM paramaters (e.g. for Sun JDK 6 64 bits -XX:+UseParNewGC switch leads to leak PermGen segment of memory. If you add additional switches: -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled-XX:+CMSPermGenSweepingEnabled the situation will be resolved. Funny, but I never met above mentioned leak with Sun JDK 6 32 bits). Link to an article "Tuning JVM Garbage Collection for Production Deployments".
  • Your PermGen chunk can be not enough to load classes and related information (actually that most often happens after redeploy under Tomcat, old classes stay in memory and new ones are loading)

From my past experience, debugging that kind of leak is one of the most tricky kind of debugging that I've ever had.

[UPDATED]

Useful article how to eliminate classloader link on an application redeploy.

FoxyBOA
The research I've done makes me think I can't do anything short of dumping Spring, Hibernate, log4j, and some other frameworks. All of them contribute to this problem. The only other alternative is to move all their libs to Tomcat's common/lib directory so they aren't reloaded upon redeploy
rcampbell
Other option could be switch to module based application server (e.g. OSGI based) like a http://www.springsource.org/dmserver
FoxyBOA
A: 

Perm gen is probably the simplest memory to handle, I doubt there'd be much difference between the various vm implementations.

Make sure all those Tomcat configs that are marked turn off in production are turned off in production.

Yes, some frameworks that do generate a lot of classes an the fly, but they should be cleaning up after themselves, and, in any case, you can fit more than a few classes in 128Mb.

Seriously, if perm gen keeps going up then thats a leak a should be fixed, though it may not be your problem to fix.

CurtainDog