views:

1494

answers:

7

We have an web application that uses Spring-Hibernate to persist registered users data in Oracle database. The application works fine in development environment, but when we copy it int live environment with much more data, it failed. Initially the application starts normally, but after few actions 'PermGen out of space' exception occured.

I've started to search in Google, Spring and Hibernate forums, but it doesn't help. There is many discussions about this error, but for each solution, there are people, that say: 'It works' and other people say 'It doesn't'.

For example, many people offer to increase '-XX:MaxPermSize' JVM parameter, other says that it doesn't works. There are posts that says that the problem in use of javassist library and others and cglib library needed to be used. Others says that the problem is in cglib.

We use Java1.5_0_09, Spring 2.5 with javaassist3.4.GA, Tomcat 5.5 as web-container and Oracle 10g as database.

Can anybody explain me what causes this problem and how to solve it?

+9  A: 

The -XX:MaxPermSize does work, you've just got to get the right value. The default, I believe, is 32mb for t the client-mode VM, and 64mb for the server mode VM. I suggest setting it to 256mb, if you have the memory:

java -XX:MaxPermSize=256m

The problem occurs because Spring and Hibernate can make heavy use of runtime-generated classes, sometimes a lot of them. These generated classes all go into the PermGen memory pool, so if you use those frameworks, you often need to boost your PermGen to large amounts.

skaffman
And be aware that this only delays the problem. If your application generates classes on a regular basis you'll have to restart your server every now and then.
Stroboskop
Sadly, yes. It seems we're pretty much stuck with it.
skaffman
+2  A: 

As skaffman says the -XX:MaxPermSize property does work, however sometimes you can have an underlying problem that upping the limit may only defer.

Have you seen this note? It helped me resolve a similar problem once. To summarise the link:

  • Put JDBC driver in common/lib (as tomcat documentation says) and not in WEB-INF/lib
  • Don't put commons-logging into WEB-INF/lib since tomcat already bootstraps it
Rich Seller
+3  A: 

I have seen this problem with Hibernate (used without Spring). The issue there was that we were creating an instance of a SessionFactory for each user request rather than creating a single instance for the lifetime of the application.

I used the YourKit profiler to investigate this and discover the issue.

Matthew Murdoch
+4  A: 

You must be aware that some versions of Tomcat have memory leaks on war redeployment. It happened to me on tomcat 6.0.x.

As suggested increase the MaxPermSize, this is a temporary solution for your development machine - and when you get the error, after 2-3 days, just restart the server. On production is not that simple. So this works for development, but this approach doesn't work for production, where you should have the memory leaks issues fixed.

To discover the leaks use the jconsole application that comes with jdk 1.6 and 1.5. You can bind to a process, and watch memory used over time.

You can also read these:

Mercer Traieste
A: 

Visual GC, now part of JDK 6, gives a very nice graphical representation of memory in real time. You can see what's happening to eden, generational, and perm spaces. You just won't see why.

UPDATE: It's bin/jvisualvm.exe in my JDK 1.6.0_13 distro. Give it the PID of the process you want to monitor.

duffymo
That's interesting. The PermGen pool is famously opaque, and not visible to the JVMTI debug interface. I wonder how Vidual GC gets a look in there?
skaffman
A: 

All responses here relates to PermGen problem that happens because of several restarts of web-app, but in this case the problem already happens on first deployment after tomcat restart, so it can't be the problem of ClassLoader's references or commons-logging.

A: 

If you're running on jdk6 then you can use the jconsole app to monitor the memory usage of the application and investigate further.

Another avenue to pursue is to use a profiler, I use JProfiler, and take a look at the application with that. It will tell you exactly where the problem is coming from.

Michael Wiles