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: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to