-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: PermGen memory leak when creating many SessionFactories?
PostPosted: Fri Jun 16, 2006 8:03 am 
Newbie

Joined: Tue Nov 22, 2005 12:09 pm
Posts: 1
Location: Sweden
Hibernate version:
3.1.3

Full stack trace of any exception that occurs:
2006-05-12 01:14:15,387 ERROR SocketListener0-1 proxy.BasicLazyInitializer CGLIB Enhancement failed: com.test.MyBean
2006-05-12 01:14:15,479 ERROR SocketListener0-1 proxy.BasicLazyInitializer net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
2006-05-12 01:14:24,121 ERROR SocketListener0-1 tasks.BaseTask -run() Throwable: PermGen space
2006-05-12 01:14:24,121 ERROR SocketListener0-1 tasks.BaseTask java.lang.OutOfMemoryError: PermGen space.

Name and version of the database you are using:
DB2 8.2.2
DB2 8.1.6
DB2 8.1.3
HSQLDB 1.8.0.4


Description
The memory leak has been reproduced both on Win and Linux, with jdk1.5.0_06.

I have an application/service that use a large number of different db users against one database. The service is called to perform predefined, similar, tasks against different schemas with separate users. For each task only one or a few connection setups are needed.

Since tasks are not performed concurrently, connection pools may remain unused for ~5-60mins. Keeping lots of of resources and unused connections per instance of this service seemed unnecessary, especially since there are several other applications and servers that use the same database. (Even though the connection pool could be configured to use a small min-size...)

So, each task created the required SessionFactories and when done they would call close() on the SessionFactory and discard it.

When debugging the application with jconsole it was very obvious that it leaked memory in the PermGen space and in the test environment it crashed after some time. But if we kept the SessionFactories open and reused them, the server remained stable.

To isolate the problem I created a simple loop that just creates and closes SessionFactory instances and the problem remained:

Code:
SessionFactory sf;
Configuration cfg = new AnnotationConfiguration()
                .addAnnotatedClass(Service.class);
while (true)
{
  sf = cfg.buildSessionFactory();
  Session s = sf.openSession();
  Query q = s.createQuery("from Service");
  for (Service row : (List<Service>) q.list()) {
    System.out.println(row.getSName() + " " + row.getSDescription());
  }
  s.close();
  sf.close();
}


I have tried this with and without hibernate-annotations (not that it should matter?), with c3p0 and with a simpler home-made ConnectionProvider, with different mappings, and with different JDBC-drivers (DB2 and HSQLDB). But the result is always the same; the test grows in PermGen memory and finally it just stops executing.

So, before I start digging deeper into this; does anyone know why this happens? Perhaps SessionFactories are not supposed to be used in this way (created and destroyed often during runtime)? Could it be ehcache or cglib that are not pleased with this approach? I could not find any posts that was clearly related to this issue and I'm quite new to hibernate.

Even if I decide to keep all SessionFactory instances between tasks it would be interesting to know why this error occurs...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 9:34 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Proxy class cache has session factory scope and proxies are regenerated if you reopen factory (old class can not be unloaded if class loader is referenced). Factory is thread safe, use it as singleton and close it in context listener to stop background threads (some pool or cache implementations can create threads).


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 02, 2006 9:59 am 
Beginner
Beginner

Joined: Sat Jan 31, 2004 7:19 pm
Posts: 39
What does this mean:

old class can not be unloaded if class loader is referenced


If the classloder hangs on to registered classes, isn't there a way to unregister them?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 02, 2006 11:41 am 
Beginner
Beginner

Joined: Sat Jan 31, 2004 7:19 pm
Posts: 39
It appears that the Tomcat WebAppClassloader is indeed holding on to
references of the loaded classes.

See: http://issues.apache.org/bugzilla/show_bug.cgi?id=39945


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 02, 2006 4:09 pm 
Regular
Regular

Joined: Tue Mar 07, 2006 11:18 am
Posts: 54
Location: Berlin
mschulz wrote:
It appears that the Tomcat WebAppClassloader is indeed holding on to
references of the loaded classes.

See: http://issues.apache.org/bugzilla/show_bug.cgi?id=39945



This is a quiet common problem with application server / servlet container. If you are keen to get more information on that see:

http://opensource.atlassian.com/confluence/spring/display/DISC/Memory+leak+-+classloader+won%27t+let+go


simon


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 02, 2006 5:44 pm 
Beginner
Beginner

Joined: Sat Jan 31, 2004 7:19 pm
Posts: 39
...puting pedantic hat on

Now that the same mistake has been made twice in writing, once by
baliukas above and then in the link
http://opensource.atlassian.com/conflue ... 27t+let+go
where the first two lines a contradictory:

- Memory leak - classloader won't let go
- Memory leaks where the classloader cannot be garbage collected

let me tell y'all that these are actually two quite different problems.

Classloader referenced
If an app server's Classloader is not gc'able because it's still being
referenced, that will mostly affect people trying to reload a webapp
dynamically, but overall it's soemthing people can usually work around one way or another.

Classloader referencing other classes
On the other hand, if a Classloader prevents the classes it loads from
being garbage collected, that may affect a running server adversely,
and all you can do about it is to make the PermGen larger or reduce
usage of CGLIB, Hibernate, Spring et al.

So to be clear about this, Tomcat's WebAppClassloader is an offender
of the second category, while most of the discussion I see going on
is about the first category.

On the upside, Tomcat will only have to be fixed once, while those
static fields are a real pita to root out.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 03, 2006 6:41 am 
Beginner
Beginner

Joined: Wed Feb 04, 2004 5:21 pm
Posts: 37
I suggest that you create singleton objects to hold your SessionFactories using Spring/HiveMind. They really are factories, and as such there is no reason to discard them until the application closes.

If you are implementing a web application there is documentation elsewhere on how to set it up.
Have a look at Spring frameworks HibernateTemplate. Although I use my own variation of the idea, I'm sure it will give you a great starting point.

Cheers,

Henrik


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.