-->
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.  [ 3 posts ] 
Author Message
 Post subject: SearchFactoryImpl, ThreadLocal, and Classloader memory leak
PostPosted: Wed Nov 19, 2008 5:56 pm 
Newbie

Joined: Wed Nov 19, 2008 4:32 pm
Posts: 1
Hibernate version: 3.2.6.GA (Hibernate Search 3.0.0.GA)


There is a ThreadLocal in org.hibernate.search.impl.SearchFactoryImpl that doesn't get cleaned up properly. This cause problems for hot-deploying to an application server if the hibernate jars are in the war file. When that's the case the ClassLoader cannot be garbage collected because SearchFactoryImpl.contexts is a ThreadLocal which lives in the threadLocal map inside the Thread instance for the current thread which was loaded (most likely) by the system classloader. However if hibernate is in the war then the SearchFactoryImpl class will be loaded by the WebAppClassloader and the SearchFactoryImpl.context is a static field and keeps SearchFactoryImpl.class from being collected which keeps WebAppClassloader around. This in turn keeps every class loaded in the war which will cause the JVM to run out of permgen space quickly.

A workaround is to use reflection to manually remove the threadlocal:
Code:
Field field = SearchFactoryImpl.class.getDeclaredField("contexts");
field.setAccessible(true);
ThreadLocal<?> threadLocal = (ThreadLocal<?>) field.get(null);
threadLocal.remove();


Looking at the source for SearchFactoryImpl I can see that the ThreadLocal contexts has a WeakHashMap stored and the set and get methods are called on the ThreadLocal but nothing is ever done to remove the ThreadLocal when it's no longer needed.

Note that people that use the hibernate that's in the %JBOSS_HOME%\lib folder won't have this problem. Or rather, they won't notice this problem because hibernate is loaded by the same classloader as the rest of JBoss and doesn't get unloaded when a war is hot-deployed. However that's not a satisfactory solution because our application (like many others I assume) needs to be able to be deployed on a number of application servers and we cannot count on them all having hibernate built in. Also we want to control which version of hibernate is being used so our persistence code doesn't break.

Here's some method calls to get to where this SearchFactoryImpl.context is created. Maybe this will help in figuring out when the ThreadLocal should be removed:

org.hibernate.search.impl.SearchFactoryImpl.getSearchFactory()
org.hibernate.search.event.FullTextIndexEventListener.initialize()
org.hibernate.cfg.search.SearchConfiguration.enableHibernateSearch()
org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory()
org.hibernate.jmx.HibernateService.buildSessionFactory()
org.hibernate.jmx.HibernateService.start()

Looking at what happens when HibernateService.stop() is called, there's nothing that gets back to the SearchFactoryImpl to remove that ThreadLocal.

EDIT: It should be noted that while I'm calling this problem a memory leak, by Sun's definition this isn't a leak because it is not unbounded over time. One hot-deploy / undeploy causes the permgen space to grow by a fixed amount. As long as you don't redeploy, you could still run forever. However if you set up a commandline loop to say ... touch the war file every 40 seconds and do that about 100,000 times in a row ... it will crash with a permgen space out of memory exception after about 5-10 reploys (depending on the size of the war file). So why this technically isn't a "leak" per se, it behaves like a leak under the right circumstances. Just thought I'd add that :)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 23, 2008 2:37 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
thanks this is very informative;
You are welcome to open a JIRA request for this, it looks quite important;

I'm not sure however if this is easy to fix, we (as developers) are quite annoied by this threadlocal too, but it is currently used for some important stuff I don't currently remember ;-)
The priority was not as high because it didn't look to cause any problem; this will change probably if you report this.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 01, 2008 4:18 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
If you like to, you're welcome to join the dev list: there's some chatting about this.
I would appreciate your opinion, and maybe you could test some solutions.

Also, if you used the "autoregistration" feature from newer versions of hibernate-annotations, you wouldn't need to declare the FullTextIndexEventListener in your configuration and the ThreadLocal
wouldn't be used. Could you test that?

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 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.