wood burning stoves 2.0*
The moose likes Struts and the fly likes Object persistance causing OutOfMemoryError Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Frameworks » Struts
Bookmark "Object persistance causing OutOfMemoryError" Watch "Object persistance causing OutOfMemoryError" New topic
Author

Object persistance causing OutOfMemoryError

Ed Latimer-Sayer
Greenhorn

Joined: Oct 12, 2004
Posts: 8
Ok i've got problem, and I really hope it's just something daft i've done.

I'm working on an enterprise web app, using Struts, EJBs, and iBatis. It's all running on Orion with a mySQL backend. Now everything works fine functionally, but after some load testing Orion crashes with java.lang.OutOfMemoryError.

I've been using jProfiler to find where the leak is and have noticed that all the objects created when a call to the back end is made are persisted. They don't get garbage collected even after logging out and invalidating the session. The users ActionForms are removed, but not the ValueObjects i create to move the data across the tiers. It's as tho everything called by the Action to satisfy a request is persisted - even after session timeout.

All my Actions are session scope, so i tried changing the login and homepage actions to request scope and just load test the login functionality but the objects still persist - even when you force garbage collection on the JVM.

I've also tried setting everything to NULL after i've used it, so the iBatis sqlMaps, the record set Value Objects in the action after i've set the content on the form, the EJB instances, everything... but still everything is persisting.

I'm at a loss now , having spent a couple of days searching the developer Forums with no luck - any help would be greatly appreciated.

Thanks in advance... Ed.
Kedar Dravid
Ranch Hand

Joined: May 28, 2004
Posts: 333
Well, I had a similar problem when working with Torque, another object-persistence layer. As it turned out, I was getting the error because I had got my loop, for retrieving records from the tables(of course, using objects) slightly wrong - in my case, I had used a while loop instead of an if loop.
I don't know whether this helps u, but checking the loop conditons did help in my case.
Ed Latimer-Sayer
Greenhorn

Joined: Oct 12, 2004
Posts: 8
Thanks for the reply Kedar, i have used while loops in some cases - but checking through the code i've not used any during the login or homepage UCs which still give me the OutOfMemoryError. I'm surprised that a WHILE loop would make objects persist and an IF loop wouldn't, is there a reason for that?

Most of the time the objects that are returned from the dB are returned in a List from iBatis, so all i need to do is return that to the Action and set it on the users ActionForm. Looking at how the memory that persists is allocated, it all seems to stem from the initial HTTP request hitting the ActionServlet, then to my specific Action class which calls a method on the EJB, on through iBatis and then back again...

It looks like all the users session stuff is removed, but none of the memory used in making the call to retreive the data is discarded. The EJBs are stateless session beans, and the Actions are session scope - but even setting them to request scope didn't help. It appears as tho the ActionServlet is holding on to the start of the call chain so none of it gets freed up. I was using Struts 1.1, but upgraded to v1.2.4 hoping it might help but it didn't...

This memory issue is preventing the application going live, as all the other testing is complete. It's now the only thing holding up the project so i'm starting to sweat, i wish I had an idea of what might be causing it... any other suggestions/sympathy greatly appreciated.

I might be interpreting the information from jProfile incorrectly and chasing my tail, so any pointers would be good on that.

One stressed developer... Ed.
Ed Latimer-Sayer
Greenhorn

Joined: Oct 12, 2004
Posts: 8
ok, an update... i'm getting to grips with jProfiler a bit more now and think that it's the iBatis static SqlMap instances that i'm creating in my EJBs that are not freeing up resources. I'm setting them to NULL after i've used them but they are still not getting cleaned up.

This is the code from one of my Stateless Session Beans, and i've also included the code from the SqlMapConfig class that returns the sqlMap instance... i have edited the standard one to return a specific one for each type of dB access.

<ejb code>

public List getAnnoucements(Date todaysDate) throws SQLException
{
// Get configured SqlMap instance
SqlMap sqlMap = SqlMapConfig.getSqlMap(Constants.APP_READ);

try
{
// Execute the query
List results = sqlMap.executeQueryForList("selectXXX", todaysDate);
sqlMap = null;
return results;
}
catch (Exception e)
{
// throw as SQL exception
throw (SQLException)e.fillInStackTrace();
}
}

</ejb code>

<SqlMapConfig code>

public class SqlMapConfig
{
// Get instance of Log4j logger
static Logger logger = Logger.getLogger(SqlMapConfig.class);

// -- SqlMap instances are thread safe.
protected static final SqlMap sqlMap_appRead;
protected static final SqlMap sqlMap_appWrite;
protected static final SqlMap sqlMap_loginRead;
protected static final SqlMap sqlMap_loginWrite;

static
{
try
{
if(logger.isDebugEnabled()) logger.debug("SqlMapConfig called");
// -- Load the SQL Map configuration XML file a Reader or a File, referenced from the classes directory.
// -- The iBATIS common library includes a handy Resources utility class perfect for this.

// -- You can disable XML validation, it is enabled by default.
// XmlSqlMapBuilder.setValidationEnabled(false);

// Use the XmlSqlMapBuilder to build the SQL Maps from the reader.
sqlMap_appRead = XmlSqlMapBuilder.buildSqlMap(Resources.getResourceAsReader("sqlmaps/SqlMapConfig_appRead.xml"));
sqlMap_appWrite = XmlSqlMapBuilder.buildSqlMap(Resources.getResourceAsReader("sqlmaps/SqlMapConfig_appWrite.xml"));
sqlMap_loginRead = XmlSqlMapBuilder.buildSqlMap(Resources.getResourceAsReader("sqlmaps/SqlMapConfig_loginRead.xml"));
sqlMap_loginWrite = XmlSqlMapBuilder.buildSqlMap(Resources.getResourceAsReader("sqlmaps/SqlMapConfig_loginWrite.xml"));

if(logger.isDebugEnabled()) logger.debug("SqlMaps built ok!");
}
catch (Exception e)
{
// If we fail here we just want to fail gracefully.
// Errors at this point will be unrecoverable and we
// want to know about them at system startup time,
// not after hours of operation.
throw new NestedRuntimeException("Error initializing SqlMap. Cause: " + e, e);
}
}

/**
* Gets a SqlMap object based on the requested mapType
* @param mapType
* @return SqlMap object
*/
public static SqlMap getSqlMap(String mapType)
{
// Return the specific SqlMap type, appRead is returned by default.
if (Constants.APP_WRITE.equalsIgnoreCase(mapType))
{
if(logger.isDebugEnabled()) logger.debug("app_write sqlMap returned");
return sqlMap_appWrite;
}
else if (Constants.LOGIN_READ.equalsIgnoreCase(mapType))
{
if(logger.isDebugEnabled()) logger.debug("login_read sqlMap returned");
return sqlMap_loginRead;
}
else if (Constants.LOGIN_WRITE.equalsIgnoreCase(mapType))
{
if(logger.isDebugEnabled()) logger.debug("login_write sqlMap returned");
return sqlMap_loginWrite;
}
if(logger.isDebugEnabled()) logger.debug("app_read sqlMap returned");
return sqlMap_appRead;
}
}

</SqlMapConfig code>

Sorry for the long post, but i thought the more info the better. Thanks in advance, Ed.
Ed Latimer-Sayer
Greenhorn

Joined: Oct 12, 2004
Posts: 8
Problem solved I think (fingers crossed)... upgraded to iBatis version 2.0.7 and all my memory issues seemed to have evaporated. That will teach me to always use the latest version :roll:
Dark Vachor
Greenhorn

Joined: Oct 13, 2004
Posts: 14
Using the lastest version might leave you with bugs anyway.

Why don't you all use better software, tested and validated, instead of using all piece of crap you stumble on ? Many applications have problems with "not so tested" "frameworks".

Think of this :
A software that works is a software that uses good framework/libraries/tools on a working OS on working harware on working network.
If you do not qualify you tools/frameworks/libraries, you miss the point.
Ed Latimer-Sayer
Greenhorn

Joined: Oct 12, 2004
Posts: 8
Interesting point, tho I don't quite see it that way. We spent some time evaluating and testing different frameworks, and thought about writing our own. Any software may contain bugs, including code that you've written yourself, the key to validating the code - is proper testing in many different conditions.

That fact that iBatis, struts, hibernate and other frameworks are being used by thousands of people, in a thousand different configurations gives me more confidence that the code is being proven than even some of my own code that has only been tested locally under safe conditions.

If you have a problem integrating with other peoples code does that mean that you write your own dB drivers, JVM, and OS?
Dark Vachor
Greenhorn

Joined: Oct 13, 2004
Posts: 14
If you have a problem integrating with other peoples code does that mean that you write your own dB drivers, JVM, and OS?

Of course I do not. Writing my own web framework or other framework stuff is no good idea to me. There are so many people out there willing to do it. And some do a good job. What I say is that if I choose a framework / tool, I need to evaluate it and be confident that thousands people used it and are satisfied with it, good documentation, mailing list, bug notification and report, etc. The tools must keep a simple and fonctional approch too. Tomcat and hibernate are good enough for me. Struts might be a good tool, bit it's too heavy to learn for my developers for the benefits we will pull out of it. Moreover it is not compatible with web sites editing tools to make great looking web sites.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Object persistance causing OutOfMemoryError