There are lots of posts about why we need to recycle objects in Java.
What I don't understand from the IBM example below is why recycling the "doc" variable is deemed useful but the "temp" variable is not .
I totally understand that if you recyle the place holder variable then you need a "temporary" variable for the getnextdocument() to work but why not just have one variable and recycle that variable after the loop
Why is the cost of not recycling "Temp" acceptable where as the cost of not recycling "doc" is unaccptable.
http://www-01.ibm.com/support/docview.wss?uid=swg21097861
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 resave, 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();
}
}
}
The key is understanding what recycle does. Recycle does nothing to a variable (e.g. doc, tmp). Recycle clears the handle to a C++ object corresponding to a document, a database, whatever. So consider the following code:
Document tmp = dc.getNextDocument(doc);
doc.recycle();
doc = tmp;
You're recycling the handle to the C++ object you've just iterated. Now consider:
Document tmp = dc.getNextDocument(doc);
doc = tmp;
tmp.recycle();
You're not recycling tmp. You're recycling the handle to the Document you've assigned to tmp. That handle is also assigned to the doc variable. So when you try to call doc.getFirstItem("myField"), you get the error that the object has been recycled or removed. Because by recycling tmp, you've also recycled doc, because you're recycling the handle to the underlying C++ object. You also no longer have a Java variable relating to the previously iterated Document. So you have no way to recycle that object.
It's also why tmp or doc do not need recycling after the loop. The final iteration tries to get the next Document after the last in the collection. That is null, so no handle to a C++ object has been retrieved. So because no handle has been retrieved, there's nothing to recycle.
It's also why you only really need to recycle in loops. In 8.5.0 the number of handles I accessed before crashing a server was about 20,000. That's been increased in 9.0. Ignore the loops and the number of handles most code will on an XPage will have open at any one time is less than 100. So why waste your effort recycling when you'll never crash a server if you don't? Because at the end of the request, the Session will be recycled, along with all its descendants - so any C++ handle you are likely to have accessed.
But you may need to recycle more than just Document or ViewEntry objects in loops. Any call to getColumnValues() for a view that contains dates will create a DateTime object, even if you don't use that column in your code. That DateTime is a child of the Session, not the ViewEntry being iterated. So you need to call .recycle(colVals), passing in the Vector that contains the column values to any Domino object that has not yet been recycled. Any Name or DateTime object created in the loop also needs recycling.
Java memory is regularly garbage collected, so there should not be a need to set variables to null.
See Nathan's comment on my blog post from Dec 2009 when I first hit it with SSJS http://www.intec.co.uk/go-green-and-recycle-the-important-information-any-non-java-xpages-dev-needs-to-know/ and my blog post on the perils of getColumnValues() http://www.intec.co.uk/the-perils-of-getcolumnvalues-get0/
Every document gets its own handle.
If you would write doc = v.getNextDocument(doc); you wouldn't have a chance to recycle the "old" document. If you would do it before the line then getNextDocument() would fail because parameter doc is gone already and afterwords you can't recycle it because variable doc points to the new document already.
So, the trick is to keep the "old" document in variable doc, put the next document into variable temp, recycle doc and assign temp to doc.
It sounds inefficient to use the additional temp variable but actually it is just an additional pointer to the document object and therefore only little memory usage.
While-block will be finished when next document is null. At the end of while-block temp and doc will be null and don't point to a document anymore and that's why temp or doc don't need to be recycled after while-block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With