Be kind to your Domino server when using Java... recycle()
Joe Litton and I are preparing a session for next month's meeting of the Portland Domino-Notes User Group that will cover Java For The Domino Developer. The focus will be taking what you already know about LotusScript and relating it to writing Domino agents in Java. Think of it as a short-cut method to getting started with learning Java...
One of the items we'll cover is the use of the "recycle()" method of each Domino object when coding in Java. This is a critical item that Joe learned all too well when he was working on a project for a former employer. As in crashing the mail server each night until he learned about this feature... :-)
From the KnowledgeBase...
Why it is Important to Use Recycle() Method on Every Java Object That is Created
Document Number:
1097861
Problem
You want to use Java in either an agent,
a servlet, an applet or a stand-alone application to access Notes Objects.
This can be used to access information locally on the same server
or remotely on a different server, in which case CORBA (Common Object Request
Broker Architecture) would be used. All of the above have been created
to mimic the LotusScript Object Model and make it easier for developers
to use these tools. For example, to get a handle on a database using
LotusScript, the session contains the current database. This is also
true for the Java classes. Once you create a session, you may reference
a database through the session. When does a developer need to invoke
the method recycle() for this code?
Content
When you create an object in LotusScript,
you create two objects - one in LotusScript and one in the Notes back-end
(C++ code). The LotusScript object "points" to the C++ object,
which really implements the class's behaviors. When the LotusScript
agent or event ends, both objects are destroyed automatically. If
the objects were not, they would stay resident in memory thereby creating
a memory leak.
If you create an object in Java, the
same applies - it's a pointer that points to an object that is created
in C++. It is common in pure Java coding to set something to null
in order for it to be flagged for garbage collection (gc) immediately,
and this is called "aggressive" garbage collection. However,
when using the Notes Objects for Java, setting something to null marks
the Java object for garbage collection, but does not mark the C++ object
for garbage collection. De-referencing the Java Object flags it for
garbage collection, but nothing will be affected on the C++ Object. Recycle()
destroys the C++ object and sets the Java object for garbage collection.
If you mark things null, you could still experience memory issues.
When using objects in an Agent all objects (both Java and C++) are
destroyed when the agent ends. When using servlets, JSPs or standalone
applications recycle must be used as Domino will never clean up these backend
objects
Conversely, if an object has been set
to be recycled, it will not be marked null. You could, in theory,
reference the object again - it shouldn't crash, it would merely throw
an exception. This is important when there are multiple references
to the same object; "db = mydb.nsf" as well as, later on "db
= yourdb.nsf". Redefining your reference in this manner is not
recommended. It can be confusing and can therefore yield unreliable
results.
In a perfect world, the developer needs
to be sufficiently familiar with the application to understand what objects
are created, what they are set to and when they are used. However,
developers often inherit code to manage with which they are not familiar.
One thing that's important to know is that the objects form a hierarchy.
That is, recycling a parent - such as a document - will recycle it's
children - such as an item. Since the session object is at the top
of the hierarchy, recycling the session will recycle everything that has
been used from it.
One thing that you can do is go to the
design pane in Domino Designer and click in the code area and do a Find
on "recycle" or whatever object for which you may be searching.
Set the scope of the Find for current or all objects. If you
do a search for recycle()s and don't find any, then the first thing that
should be done is to remedy the situation by having the developer go through
and add this bit of code to all objects after they are finished being used.
One thing to watch out for is the use of New being instantiated in
a loop. For every iteration of the loop and new object is created.
Unless you recycle() the object within the loop this object will
stay resident in memory.
Here's an example of using recycle()
within a loop as well as using aggressive garbage collection:
import lotus.domino.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext =
session.getAgentContext();
Database db = agentContext.getCurrentDatabase();
View v = db.getView("SomeView");
// turn off auto-update so that if we make a change to a document and re-save
// it won't affect the sort order in the
view
v.setAutoUpdate(false);
Document doc = v.getFirstDocument();
Document temp = null;
//sets the temp for garbage collection immediately
while (doc != null)
{
// do something with the document here...
// whatever, just don't delete it
(yet)!
temp = v.getNextDocument(doc);
// get the next one
doc.recycle();
// recycle the one
we're done with
doc = temp;
} // end while
} catch(Exception e) {
e.printStackTrace();
}
}
}



Comments
Posted by Colin Pretorius At 07:47:07 On 15/10/2003 | - Website - |