Are you doing any server side caching of the data? If so perhaps your caching mechanism is re-caching the same data per request?
As Charles said earlier, your best bet would be to use a profiling tool that will tell you exactly where the memory is being allocated. -----Original Message----- From: Ken Bowen [mailto:[email protected]] Sent: Wednesday, January 20, 2010 7:11 PM To: Tomcat Users List Subject: Re: memory leak As I mentioned, the DAO class uses a standard try/catch/finally pattern to ensure that all statements, resultsets, & connections have been closed before a method returns. On Jan 20, 2010, at 9:25 PM, Travis Beech wrote: > I would make sure that your DAO class is closing any statements, > resultsets, and connections that are no longer being used once your > method call returns. > > Since GC does happen immediately your db resources could still be in > memory. > > Travis Beech > > On Jan 20, 2010, at 3:50 PM, Ken Bowen <[email protected]> wrote: > >> Short version: I have a project which gets some simple info from a >> db via DWR, and outputs it simply on the page. There is a memory >> leak on the java side. >> >> Longer version: >> I've developed a project using JSPs and the Ajax tool DWR 2.0 >> (Direct Web Remoting: http://directwebremoting.org/dwr). >> I've used Java 1.6, and am running the project on Tomcat 6.0.20 on a >> remote CentOS 5 VPS with 288MB memory. {I know that my problem may >> lie in my (mis)use of DWR, but I'm starting here to clarify my >> (possible lack of) understanding about JSP memory usage and Tomcat.} >> >> The app consists of a number of independent tasks, one of which >> (LISTALL) just asks for a list of all the html web pages (about 550) >> available from a certain collection. The payload shipped to the >> browser is roughly 140K, just consisting of a list of authors and >> titles and urls to the relevant pages. >> >> Using top, I've observed that when I repeatedly run this LISTALL >> request, the resident memory increases about 1Meg for every >> approximately ~10 reloads of the page. If I turn of javascript in >> the browser and repeatedly reload the page, there is no change in >> the resident memory (as naturally expected). It is suggestive the >> 140k * 10 is in the ballpark of 1Meg. >> >> The LISTALL request is contained in the javascript for onPageLoaded >> () on a very simple JSP page which simply displays the data, >> together with some Amazon and Google ads. >> >> The LISTALL request simply makes a call >> StoriesAccess.getAllAuthorsAndTitles through the DWR servlet: >> >> http://<mydomain>/dwr/call/plaincall/ >> StoriesAccess.getAllAuthorsAndTitles.dwr >> >> The StoriesAccess class contains no instance variables and consists >> of a collection of methods to be invoked for their callbakcs (the >> dwr servlet makes the return values of the methods available to the >> javascript as a callback). The getAllAuthorsAndTitles is very >> simple: It makes several calls to the (MySQL) db to obtain the >> data, and assembles a bean which it returns. >> Basically: >> public AuthorsWithTitles getAllAuthorsAndTitles(long userNum) >> { >> // the data bean to be returned >> AuthorsWithTitles result = new AuthorsWithTitles("all"); >> >> // db call to get all the story data >> CustomSbDataDAO csbddao = new CustomSbDataDAO(); >> List<Story> alist = csbddao.retrieveStoryAll(); >> >> // holds individual "author + titles" classes being >> assembled: >> HashMap<Integer,AuthorAndTitles> hres = new >> HashMap<Integer,AuthorAndTitles>(); >> >> Iterator<Story> stories = alist.iterator(); >> while (stories.hasNext()){ >> Story story = stories.next(); >> Integer authorNum = story.getAuthorNum(); >> >> AuthorAndTitles aat = hres.get(authorNum); >> if (aat == null){ >> Author author = csbddao.retrieveAuthorByPrimaryKey >> (authorNum); >> aat = new AuthorAndTitles(authorNum, >> author.getAuthorLN(), author.getAuthorFN()); >> hres.put(authorNum, aat); >> } >> XStory xstory = new XStory(story); >> aat.addStory(xstory); >> } >> // this will be the actual list of "author + titles" >> returned: >> ArrayList<AuthorAndTitles> initATs = new >> ArrayList<AuthorAndTitles>(); >> initATs.addAll(hres.values()); >> >> // sort by author, and sub-sort by assigned title letter >> of story: >> Collections.sort(initATs, new Comparator<AuthorAndTitles>() >> {...comparator....} ); >> Iterator<AuthorAndTitles> aTs = initATs.iterator(); >> while (aTs.hasNext()){ >> AuthorAndTitles at = aTs.next(); >> List<XStory> xstoryList = at.getAuthorStories(); >> Collections.sort(xstoryList, ...comparator...); >> } >> >> result.setAuthorsWithTitles(initATs); >> return result; >> } >> >> The class CustomSbDataDAO provides methods for accessing MySQL, and >> all connections, statements, resultsets, etc., are released using >> the standard try/catch/finally pattern. It's my understanding >> (belief) that each time the method runs, when it returns, the values >> in all the local variables become available for gc. >> >> So the obvious issue is where the leak could be occurring. DWR is >> relatively mature and somewhat extensively used, so there isn't >> likely to be simple-minded memory leak in DWR itself. Any >> suggestions for where to look or what I may be doing wrong will be >> greatly appreciated. >> >> Thanks in advance, >> Ken >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [email protected] >> For additional commands, e-mail: [email protected] >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
