tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ken Bowen <kbo...@als.com>
Subject memory leak
Date Wed, 20 Jan 2010 23:50:09 GMT
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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message