[ https://issues.apache.org/jira/browse/CXF-2164?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12702424#action_12702424 ]
Daniel Kulp commented on CXF-2164: ---------------------------------- >From a IM chat I had with Bharath: (posted here so all can benefit) (11:00:12) rbharathganesh: What Francois Masurel is saying about the ThreadLocal leak seems to be correct (11:00:39) rbharathganesh: If you look at ClientImpl we never unset the req and resp contexts (11:00:39) jdkulp: Yea, I'm just not sure how to go about fixing it. :-( (11:00:49) rbharathganesh: I have something in mind (11:00:59) rbharathganesh: Just wanted to confirm with you before doing it (11:01:27) jdkulp: The part in the WebServiceContext server side should already be fixed. (11:01:35) rbharathganesh: If you look at his latest comment on the bug: (11:01:35) jdkulp: I think he's looking at 2.1.4 code. (11:01:36) rbharathganesh: //There is no try/finally around WebServiceContextImpl.setMessageContext and WebServiceContextImpl.clear in org.apache.cxf.jaxws.JAXWSMethodInvoker invoke method. But as long no exception is throw in between it should'nt be a problem. (11:01:41) rbharathganesh: This is incorrect (11:01:48) rbharathganesh: We have already fixed this (11:01:49) rbharathganesh: Oh yes (11:01:56) jdkulp: Yea. It WAS broken in 2.1.4. (11:01:58) rbharathganesh: Sorry did not rread what you typed :-( (11:02:39) rbharathganesh: But yes the second part seems to be right (11:03:07) jdkulp: Yea. If you have a good idea to fix it, I'm all ears. :-) (11:03:31) jdkulp: Maybe a weak ref in the thread local and a strong ref in the ClientImpl? (11:04:22) rbharathganesh: hmmm.. But how about explicitly clearing it in JaxWsClientProxy? (11:04:45) jdkulp: The issue is "when to clear it". (11:05:41) rbharathganesh: In JaxWsClientProxy#invoke(), Before retuning the result to the user? (11:06:40) jdkulp: You cannot clear the response context then. (11:06:53) jdkulp: Or they obviously couldn't get the response stuff. (11:07:23) jdkulp: Plus, if you make 3 invokes, the original stuff in the context needs to still be used. (11:09:15) rbharathganesh: Dan I guess I am missing something (11:09:21) rbharathganesh: // if you make 3 invokes, the original stuff in the context needs to still be used. (11:09:23) jdkulp: or I am... :-) (11:10:04) rbharathganesh: Is there any state to be maintained beyond the scope of the invoke method? (11:10:22) jdkulp: The state of the request context is for ALL invokes on that thread. (11:10:24) jdkulp: So yes. (11:10:39) jdkulp: If I set the ENDPOINT_URL in the request context, then call invoke 10 times, all 10 should go to that URL. (11:10:54) rbharathganesh: Oh Yes! (11:16:41) jdkulp: One option could be to use a WeakHashMap<Thread, Map<...>> in client impl instead of thread locals. (11:17:03) jdkulp: Thus, when clientImpl is garbage collected, so would that map and everything it points to. (11:17:30) rbharathganesh: Yeah.... (11:17:33) jdkulp: If a thread goes away, it's map would be gc'd (11:18:47) rbharathganesh: In his case, the clientImpl goes away right? (11:18:54) jdkulp: I assume so. :-) (11:19:09) jdkulp: I think when the war/app is undeployed, it should go away. (11:19:11) rbharathganesh: The thread going away would mostly never happen right? (11:19:33) jdkulp: Maybe, maybe not. It could be a workqueue that grows/shrinks on demand. (11:19:38) rbharathganesh: The web server would anyway pool these threads (11:19:40) rbharathganesh: yeah right (11:19:40) jdkulp: In which case it COULD go away. (11:19:46) rbharathganesh: Yeah > CXFBusImpl never removed from ThreadLocal, generates permgen out of memory > error after some redeployments > --------------------------------------------------------------------------------------------------------- > > Key: CXF-2164 > URL: https://issues.apache.org/jira/browse/CXF-2164 > Project: CXF > Issue Type: Bug > Components: Bus > Affects Versions: 2.1.4 > Reporter: Francois Masurel > Attachments: cxf_threadlocal.jpg, > Heap_Walker_Incoming_References.zip, threadlocal.patch > > > I've found this message on a mailing list recently, and it doesn't seem to > have been resolved as we have the same problem with version 2.1.4 of CXF on > one of our webapp : > Hello CXF users, > I've been working on figuring out why our JBoss servers keep going down with > permgen out > of memory exceptions when we redeploy our war files. To do this I had been > using a profiler > to inspect the WebAppClassloader to find out what was keeping it from being > garbage collected. > One such culprit was the class org.apache.cxf.BusFactory > The BusFactory has a ThreadLocal in which it stores a copy of CXFBusImpl. > However, this isn't > getting cleaned up properly when the war is undeployed. I noticed that > CXFBusImpl has a shutdown > method that calls BusFactory.setDefaultBus(null) which in turn sets the value > stored in the > ThreadLocal to null. However, this doesn't seem to be getting called. > The way we are using CXF from spring is with the following > WEB-INF/services.xml file in our > war: > <beans xmlns="http://www.springframework.org/schema/beans" > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > xmlns:amq="http://activemq.org/config/1.0" > xmlns:jaxws="http://cxf.apache.org/jaxws" > xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" > xsi:schemaLocation=" > http://www.springframework.org/schema/beans > http://www.springframework.org/schema/beans/spring-beans-2.5.xsd > http://cxf.apache.org/transports/http/configuration > http://cxf.apache.org/schemas/configuration/http-conf.xsd > http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd > http://activemq.org/config/1.0 > http://activemq.apache.org/schema/core/activemq-core-5.0.0.xsd" > default-autowire="byType"> > <import resource="classpath:META-INF/cxf/cxf.xml" /> > <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> > <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> > <jaxws:endpoint id="helloService" implementor="#helloSvc" > address="/HelloService" /> > </beans> > I'm not really sure why this Bus.shutdown() isn't getting called or even who > is responsible > for calling it. I tried doing something along the lines of: > WebApplicationContext webContext = > WebApplicationContextUtils.getRequiredWebApplicationContext(context); > if (webContext.containsBean("cxf")) { > CXFBusImpl cxfBus = (CXFBusImpl) webContext.getBean("cxf"); > cxfBus.shutdown(true); > } > But that didn't work. What I eventually ended up doing was to have the > following hack in the > shutdown sequence of our webapp: > Field field = org.apache.cxf.BussFactory.class.getDeclaredField("localBus"); > field.setAccessible(true); > ThreadLocal<?> localBus = (ThreadLocal<?>) field.get(null); > localBus.remove(); > This did work but obviously it is a bit of an ugly hack. Is there something > that needs to > be included in our service.xml file to tell spring how to cleanup CXF? Is > this maybe a bug > in CXF that the CXFBusImpl.shutdown(Boolean) just isn't getting called at all > or maybe that > in BusFactory.setThreadDefaultBus(Bus) that there should be some check such > as: > if (bus == null) { > localBus.remove(); > } else { > localBus.set(bus); > } > Or maybe some combination of all of these. I'm reasonably new to CXF, Spring, > and all this > stuff so I apologize ahead of time if there is some obvious solution that I > just didn't come > across but I've been trying to scour the CXF and Spring documentation for > some idea of the > correct way to do this and why BusFactory is keeping its ThreadLocal but I > can't figure it > out. > Thanks! > Ben Dean > Software Engineer > Ontario Systems, LLC -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.