jvisualvm is an excellent tool, and so is MAT (http://www.eclipse.org/mat/downloads.php). If you can figure out which instances are increasing (as Pid indicated) its very easy to check the path of those objects to the garbage collector using one of these tools. From there its usually easy to see what the cause of the leak is and correct it. I'm not familiar with jconsole, but I have used the mat/jvisualvm approach several times before.
On Wed, May 5, 2010 at 1:36 AM, Mark Shifman <mark.shif...@yale.edu> wrote: > Thanks. > I'll try Jconsole. > mas > > On 05/04/2010 12:28 PM, Pid wrote: >> On 04/05/2010 14:10, Mark Shifman wrote: >>> >>> On 05/03/2010 02:53 PM, Pid wrote: >>>> On 03/05/2010 18:30, Mark Shifman wrote: >>>>> >>>>> On 05/03/2010 12:48 PM, Pid wrote: >>>>>> On 03/05/2010 17:15, Mark Shifman wrote: >>>>>>> I have a web app running under tomcat-6.0.26 with >>>>>>> JreMemoryLeakPreventionListener, java jdk1.6.0_18. >>>>>>> >>>>>>> Using jmap -histo pid, I can watch >>>>>>> com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl, etc increase in >>>>>>> number >>>>>>> after running my unmarshal action, followed by undeploy and redeploy. >>>>>>> Find Leaks in the manager also finds leaks. >>>> >>>> Do you see log messages referring to potential leaks in the catalina.out >>>> log (assuming you're on a unix variant)? >>>> >>>> If so, can you post them please? >>> >>> There are no messages in catalia.out concerning leaks (I am using Linux >>> 2.6.18-92.1.22.el5) >>> I also got rid of timeBetweenEvictionRunsMillis in datasource since it >>> causes a leaky TimerThread). >>> >>>> >>>> What does the manager 'find leaks' command report exactly? >>> ... >>> leak (use a profiler to confirm): >>> /yp_results >> >> There are some useful commands in the JDK which may help track down >> exactly which class is causing the problem. >> >> jmap -histo <pid> >> >> (and other jmap subcommands) >> >> If you take a snapshot periodically, esp after reload cycles you may be >> able to see which classes are increasing in number. >> >> >> If you can get a VisualVM working, or connect a JConsole to the remote >> VM you may be able to poke around and see which classes aren't being >> garbage collected. >> >> >>> My webapp is named yp_results. >>>> >>>>>> After a few undeploy/redeploy cycles does the number of >>>>>> WebappClassLoader's also increase? >>>>> >>>>> Yes it increases 1 for each undeploy/redeploy cycle. >>>> >>>>> snip... < >>>> >>>>>> Maybe. >>>>>> >>>>>>> JAXBContext.newInstance() can take a ClassLoader argument. Is there >>>>>>> some ClassLoader I should be using that will get around this? >>>> >>>> OK, so I've looked at JAXBContext (and JAXBContextImpl) and it doesn't >>>> (after quick read through) look like it's storing the classloader >>>> argument anywhere during the newInstance call, which is the usual source >>>> of leaks. >> >> >>>>>> Where is the jar with the above code, in a webapp? >>>>> The code above in in the war for the web app in a class in >>>>> WEB-INF/classes/org/blablabla >>>>> >>>>> It is called via a class that looks like this: >>>>> >>>>> public class JAXBMascot { >>>>> protected static Log log = LogFactory.getLog(JAXBMascot.class); >>>>> private XMLEventReader reader; >>>>> private Unmarshaller u = >>>>> JAXBContextMascot.INSTANCE.createUnmarshaller(); >>>> >>>> You're setting the XMLEventReader, Unmarshaller & InputStream as >>>> instance field values, rather than completing the parsing in the >>>> getInstance() method? >>> I have really big xmls to unmarshall so I am using streaming them in and >>> unmarshalling the elements I want >>> and then insert into my database. I need the reader to see where I am and >>> then the umarshaller >> >> I'll have a look at the code below a bit later, am pushed for time right >> now. >> >> >> p >> >> >> >>> I didn't show the all the methods of JAXBMascot but here is workhorse: >>> public <T> T getNextElement(String theElement, String elementAfter, >>> Class <T>clazz) { >>> String elname = ""; >>> T h = null; >>> try { >>> while(reader.hasNext()){ >>> if(reader.peek().isStartElement()){ >>> elname = >>> reader.peek().asStartElement().getName().getLocalPart(); >>> if(elname.equals(theElement)){ >>> h= u.unmarshal(reader, >>> clazz).getValue(); >>> return h; >>> } >>> } else if(reader.peek().isEndElement()){ >>> elname = >>> reader.peek().asEndElement().getName().getLocalPart(); >>> if(elname.equals(elementAfter)){ >>> return h; >>> } >>> } >>> >>> reader.nextEvent(); >>> } >>> } catch (XMLStreamException e) { >>> throw new RuntimeException(e); >>> } catch (JAXBException e) { >>> throw new RuntimeException(e); >>> } >>> return h; >>> } >>> >>> It also has a close method to clean up after I have gotten all the elements. >>> public void close(){ >>> try { >>> reader.close(); >>> } catch (XMLStreamException e) { >>> //quietly >>> } >>> IOUtils.closeQuietly(jxb_in); >>> u=null; >>> } >>> I don't think I am leaving any stuff hanging around but memory leaks are >>> very sneaky. >>> mas >>>> >>>> This looks a bit odd to me, but I don't know what the rest of the >>>> instance does... >>>> >>>> >>>> p >>>> >>>>> private InputStream jxb_in; >>>>> >>>>> public static JAXBMascot getInstance(InputStream in) { >>>>> JAXBMascot m = new JAXBMascot(); >>>>> try { >>>>> m.setJxb_in(in); >>>>> >>>>> m.setReader(XMLInputFactory.newInstance().createXMLEventReader(in)); >>>>> } catch (Exception e) { >>>>> log.fatal("error getting JAXBMascot instance"); >>>>> IOUtils.closeQuietly(in); >>>>> throw new RuntimeException(e); >>>>> } >>>>> >>>>> return m; >>>>> } >>>>> .... >>>>> } >>>>> >>>>> This is also in the webapp in WEB-INF/classes/org/blablabla >>>> >>>> >>>> >>> >> >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org