Bill F posed a good question on StackOverflow about the issue of object.recycle and when to use it. It’s un understandable question and one I hit years ago after crashing a server looping through 20,000 documents in a search. I raised a PMR, got a response directing me to technotes on recycling in Java. Searching help, wikis and other places gave me no documentation on recycling in SSJS, which gave me reason to believe I was the first to hit the problem in XPages. So I blogged about it at the time. But the absence of SSJS documentation isn’t a huge issue for understanding the concept. SSJS runs Java, so all the Java documentation holds true.
The key thing to remember is the difference between Java memory issues and recycling issues. I think Nathan T. Freeman wrote a blog post about recycling handles, but I can’t find it at the moment. Lack of recycling doesn’t cause memory issues. Each time you get any Domino object, it gets / creates the C++ object and assigns a handle so it can retrieve it. So whatever the variable name, if you’re getting the same C++ object, I believe it’s the same handle. Recycling releases that handle. There are a limit to the number of handles, and that’s the importance of recycling.
But at the end of any process (a Java agent running, an XPage loading or the rendering of a partial refresh), the Session is recycled. The other important point to note is that recycling recycles all descendants. So recycling the Session recycles any Database that was retrieves, which recycles any View in that database that was retrieved, which recycles any ViewEntry in that database.
But column values can be a gotcha. If ViewEntry.getColumnValues() just contains text or numbers, it’s not a problem. They’re not Domino objects, so there’s nothing to recycle. However, if it contains dates, then there’s a big risk. It’s most apparent if we step through exactly what happens. Consider this code:
var myString = viewEnt.getColumnValues().get(0);
It looks straightforward, any many developers (myself included) have written code like that in a loop and thought no more about it. But let’s imagine the view contains has dates in the third column. Let’s see what happens in that one line of code.
- getColumnValues() is called. An empty Vector is created with the same size as the number of columns.
- The first column is retrieved. It’s text, so the value is put in the first element of the Vector.
- The second column is retrieved. It’s a number, so the double value is put in the second element of the Vector.
- The third column is retrieved. It’s a date, so a DateTime Domino object is created as a child of the Session. A C++ handle is assigned.
- The other columns are retrieved.
- The myString variable is set with the first element of the Vector.
At the end of the loop, if you’ve coded it correctly,
viewEnt will be recycled. But that DateTime is a child of the Session, not the ViewEntry. So it won’t be recycled during the loop. Its handle will still be held for use, even though you never wanted to use it and never do use it. With the way most of us coded such loops, if we’re dealing with views with date columns, by the end of our code we’ll still have handles in use for all those DateTime objects; the total will be the number of entries iterated multiplied by the number of date columns in the view.
But you can’t recycle the Session – the parent of the ColumnValues Vector. You could iterate the Vector, get any DateTime objects and recycle the handles. Or you could use
Session.recycle(Vector), as Nathan has covered in webinars. This does that job for you, recycling any handles to C++ objects in the Vector. But for that, you’ll need to change that one line of code first written to:
var myVect = viewEnt.getColumnValues();
var myString = myVect.get(0);
You could do that.
But my preferred alternative is using the OpenNTF Domino API. Not only does it recycle DateTimes in Vectors and elsewhere for me, even if I didn’t know they should be, it also recycles anything else as soon as it can. Even without all the other functionality in the OpenNTF Domino API, that’s enough of a benefit for me, in reducing potential accidental server crashes and reducing the mount of typing I have to do.