2014-11-21 54 views
1

有很多關於爲什麼我們需要在Java中回收對象的文章。爲什麼使用臨時變量來回收XPages中的java對象工作?

我從下面的IBM示例中不能理解的是爲什麼回收「doc」變量被認爲是有用的,但「temp」變量不是。

我完全明白,如果你recyle的佔位符變量,那麼你需要一個「臨時」變量爲getnextdocument()工作,但爲什麼不只是有一個變量和循環

爲什麼是後循環變量不回收「Temp」的成本是可以接受的,因爲不回收「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(); 
 
} 
 
} 
 
}

+0

謝謝所有誰把評論的時間。我認爲所有的答案都是正確的,但保羅已經超越了(正如他經常這樣做)。 – 2014-11-24 23:51:28

回答

10

關鍵是瞭解什麼是回收。回收對變量(例如doc,tmp)沒有任何影響。回收將把句柄清除爲與文檔,數據庫相對應的C++對象。因此,請考慮以下代碼:

Document tmp = dc.getNextDocument(doc); 
doc.recycle(); 
doc = tmp; 

您正在回收剛剛迭代的C++對象的句柄。現在考慮:

Document tmp = dc.getNextDocument(doc); 
doc = tmp; 
tmp.recycle(); 

你不是回收tmp。您正在回收已分配給tmp的文檔的句柄。該句柄也被分配給doc變量。因此,當您嘗試撥打doc.getFirstItem("myField")時,會出現該對象已被回收或刪除的錯誤。因爲通過回收tmp,您也回收了doc,因爲您正在回收底層C++對象的句柄。您也不再有與先前迭代的文檔相關的Java變量。所以你沒有辦法回收這個對象。

這也是爲什麼tmpdoc循環後不需要回收的原因。最後一次迭代嘗試在集合中的最後一個之後獲取下一個Document。這是null,所以沒有檢索到C++對象的句柄。因爲沒有檢索到手柄,所以沒有任何回收。

這也是爲什麼你只需要循環回收。在8.5.0中,我在崩潰服務器之前訪問的句柄數量約爲20,000。 9.0增加了。忽略循環和大多數代碼在任何時候都會打開一個XPage的句柄數量小於100.那麼,爲什麼要浪費你的努力回收,如果你不這樣做,你永遠不會崩潰服務器?因爲在請求結束時,Session將與其所有後代一起被回收 - 因此您可能訪問過任何C++句柄。

但是,您可能需要循環使用多於DocumentViewEntry的對象。對於包含日期的視圖,任何對getColumnValues()的調用都將創建DateTime對象,即使您未在代碼中使用該列。 DateTimeSession,而不是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-dev-needs-to-know/和我的博客文章擊中它)getColumnValues的危險(http://www.intec.co.uk/the-perils-of-getcolumnvalues-get0/

4

每個文件都有自己的手柄。

如果您要寫doc = v.getNextDocument(doc);,您將沒有機會回收「舊」文檔。如果你會在行前執行getNextDocument()將失敗,因爲參數doc已經不存在了,後綴不能再使用,因爲變量doc已經指向新文檔。

所以,訣竅是將「舊」文檔保存在變量doc中,將下一個文檔放入變量temp中,回收doc並將temp分配給doc。

使用額外的臨時變量聽起來效率不高,但實際上它只是指向文檔對象的額外指針,因此只佔用很少的內存。

while-block將在下一個文檔爲空時結束。在while-block臨時結束時,doc將爲空,並且不再指向文檔,這就是爲什麼temp或doc不需要在while-block之後回收的原因。

0

從我的理解(我的知識/術語在這裏有點朦朧,我父親有人會用正確的術語),因爲每次你實例化一個新的Document對象,即使你分配給相同的Java變量底層的C++代碼實際上是創建一個新的指針(而不是重用舊指針)。

這意味着你最終會發生內存泄漏。

回收方法告訴C++代碼釋放指針,這就是爲什麼你需要在循環內執行它。

1

想象我們有看法有兩個文件

你第一次去到循環了Java doc變量「指點」到c通過循環必須++處理到Notes文檔A. 在第一次運行結束當你到達最後一個文檔時,將「temp = v.getNextDocument(doc);」指向C++句柄的文檔B的 。將返回null,文檔B的句柄將被釋放,並且瞧:-)

相關問題