Recycle Early, Recycle Often

Imagine a common Notes/Domino programming situation. You need to perform an operation on each document or examine each one in a view to find a piece of data. The code is simple in both LotusScript and Java: Get the first document in the view, do whatever you’re going to do to it or with it, and then get the next document in the view. Stop when no more documents are in the view:

Document doc = view.getFirstDocument();
while (doc != null)
{
// do something
doc = view.getNextDocument(doc);
}

As written, this loop leaks one document object’s worth of memory on each iteration. Most programs will run out of memory and crash if more than a few thousand documents are in the view. The computer reclaims the “leaked” memory only when the program terminates, so if you do this in a long-running server task (such as in a sever agent or J2EE component), you’re asking for trouble.

Because there’s no automatic, hands-off mechanism to handle this problem in Java, one had to be invented. That mechanism is the recycle() method, which exists on all Notes classes. It tells the Notes back-end classes that an object instance is no longer needed and can be destroyed. Unfortunately, this puts a bit of a burden on the developer to know what to do — leave an object unrecycled for too long and you leak memory, but recycle something too soon, and you may not have it when you need it.

The following code snippet demonstrates the correct way to prepare Domino Java objects for garbage collection.

Document doc = view.getFirstDocument();
Document temp;
while (doc != null)
{
// do something
temp = view.getNextDocument(doc);
doc.recycle();
doc = temp;
}

We get the next document using the current one, then recycle the current one before continuing the loop. This version leaks no memory whatsoever.

Developers must recognize one additional subtlety about recycling. The Notes object model enforces strict containment, meaning that every object is owned by a container object. Document, View, and Agent objects, for example, are owned by their container Database object. Database objects are owned by the Session object (this is true for all language interfaces, not just Java). So, if you recycle a container object, all its child objects will also be automatically recycled.

With the previous code sample, you might think that you don’t need to recycle each Document object inside the loop, that you can simply recycle the whole Database object from which the documents were derived when the loop is done to reclaim all the memory from each Document object. That would be true if you make it to the end of the loop without running out of memory. How lucky do you feel? Of course, if you know your program will use minimal numbers of Domino objects, you can probably get away with being less scrupulous about recycling.

Because of the strict containment rule, recycling your Session object will implicitly recycle everything created from it. So for standalone or J2EE programs, this can be a convenient approach (you can’t recycle an agent’s Session object, but Notes/Domino does it for you when the agent terminates).

Ref: Java Performance Techniques for Domino Development.