为什么使用临时变量来回收XPage中的java对象有效?

Sea*_*ull 2 java xpages

有很多关于我们为什么需要在Java中回收对象的帖子.

我从下面的IBM示例中无法理解的是,为什么回收"doc"变量被认为是有用的,但"temp"变量不是.

我完全理解,如果你重新设置占位符变量,那么你需要一个"临时"变量来使getnextdocument()工作,但为什么不只是有一个变量并在循环后循环该变量

为什么不回收"温度"的成本是可以接受的,因为不回收"doc"的成本是不可接受的.

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(); 
}
}
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*ers 10

关键是了解回收的作用.Recycle对变量没有任何作用(例如doc,tmp).Recycle清除对应于文档,数据库等的C++对象的句柄.请考虑以下代码:

Document tmp = dc.getNextDocument(doc);
doc.recycle();
doc = tmp;
Run Code Online (Sandbox Code Playgroud)

您正在将句柄回收到您刚刚迭代的C++对象.现在考虑:

Document tmp = dc.getNextDocument(doc);
doc = tmp;
tmp.recycle();
Run Code Online (Sandbox Code Playgroud)

你没有回收tmp.您正在将句柄回收到您指定的文档tmp.该句柄也分配给doc变量.因此,当您尝试调用时doc.getFirstItem("myField"),您会收到对象已被回收或删除的错误.因为通过回收tmp,你还回收了doc,因为你正在回收底层C++对象的句柄.您也不再拥有与先前迭代的Document相关的Java变量.所以你无法回收那个对象.

这也是循环后为什么tmpdoc不需要回收的原因.最后一次迭代尝试在集合中的最后一个文档之后获取下一个Document.这是null,因此没有检索到C++对象的句柄.因为没有检索到句柄,所以没有什么可以回收的.

这也是你真正需要循环回收的原因.在8.5.0中,我在崩溃服务器之前访问的句柄数量约为20,000.这个数字在9.0增加了.忽略循环和XPage上大多数代码将在任何时间打开的句柄数量小于100.那么,如果你不这样做,为什么不浪费你的努力回收你永远不会崩溃?因为在请求结束时,Session将回收它及其所有后代 - 所以你可能访问过的任何C++句柄.

但是您可能需要回收不仅仅是循环中的对象DocumentViewEntry对象.getColumnValues()对包含日期的视图的任何调用都将创建一个DateTime对象,即使您不在代码中使用该列.这DateTime是对一个孩子Session,没有ViewEntry被迭代.因此,您需要调用.recycle(colVals),将包含列值的Vector传递给尚未回收的任何Domino对象.在循环中创建的任何NameDateTime对象也需要回收.

Java内存经常被垃圾收集,因此不需要将变量设置为null.

从2009年12月我第一次点击SSJS http://www.intec.co.uk/go-green-and-recycle-the-important-information-any-non-java-xpages看看Nathan对我博客文章的评论-dev-needs-to-know和我关于getColumnValues()的风险的博客文章http://www.intec.co.uk/the-perils-of-getcolumnvalues-get0/