產品:Lotus Notes
平台:Linux,Windows
軟體版本:8.0,7.0,6.5,6.0,5.0
問題描述:
當你想要直接在本地訪問同一個伺服器的Lotus Notes objects資訊時,你可以用Java的代理(agent),小服務程式(servlet),小應用程式(applet)或者獨立的應用程式來進行。
小應用程式[applet]通過類比LotusScript物件模型,使開發人員更簡單使用這些工具。例如,通過使用LotusScript或者Java類來得到一個資料庫的控制代碼,以及包含資料庫資訊的會話(session)。一旦會話(session)被建立,你就可以通過這個會話(session)來引用相應的資料庫(database)。
然而,為了實現最佳的系統效能,回收建立過的對象是非常重要的。對於LotusScript對象或者其他的Java對象。什麼時候是調用方法Recycle()的最佳時機呢?
解答:
使用LotusScript來建立對象
當使用LotusScript來建立一個對象的時候,實際上你建立的是兩個對象:一個在LotusScript,一個在Notes後台(C++code)對象。LotusScript只是指向C++對象,而真正實作類別的行為的是C++。當LotusScript的代理(agent)或事件(event)結束後,這兩個對象將自動撤銷。如果對象沒有消除,他們將繼續儲存在記憶體裡,從而造成記憶體流失。
使用Java建立對象
如果你用Java建立一個對象,同樣是這樣的。Java對象是一個指標,指向用C++建立的對象。這在純Java代碼裡是很常見的,通過把一些變數設定為空白,使記憶體回收能夠立即執行。這種機制被稱為積極的記憶體回收。
然而,當Java使用notes對象時把相關的變數設定為空白,用來標記需要記憶體回收,而對應的C++對象並不做任何處理。那記憶體回收就只會作用於Java對象,而不會影響C++對象。
為什麼要回收?
Recycle()在回收C++對象的同時把Java對象設定為可記憶體回收的狀態。如果你只是標記對象為空白,你依舊會遇到記憶體問題。當你在代理中用對象,當代理結束時,所有的對象(無論是Java還是C++)都會被回收。當使用Java伺服器程式(Servlet),.jsp 或者獨立的應用程式的時候,Recycle()方法必須要被使用,因為Domino自己是不能清除這些後台對象的。
相反,如果一個對象設定為可回收的,它將不會被置為空白(Null)。從理論上說,你仍舊可以引用這個對象,並且不會發生重大錯誤,只不過要拋出異常(exception)。當多個引用來調用同一個的對象,這一點是很重要的,例如:“db = mydb.nsf” 和 “db = yourdb.nsf” 同時使用。因為這樣非常混亂,並且得到的結果也不可靠。
明白什麼樣的對象將被建立,將如何設定,以及什麼時候使用是很重要的。對象是一個層次的結構。例如,回收一個父文檔對象,相應的也就回收了它所有的子物件。因為會話(session)對象在整個對象層次的最上層,所以,回收一個會話(session)對象的時候,同時也回收了放在這個會話(session)對象中所有其他的對象。
查詢對象:
在Domino Designer進入設計面板,點擊代碼地區,查詢“回收(recycle)”或者任何你想要查詢的對象。並設定查詢的範圍為當前對象或者所有對象。
如果沒有尋找到任何Recycle()方法,你可以找一個開發人員來看一下,並在所有的對象使用完後加上一些代碼來回收它們。有一點需要注意,在一個迴圈裡使用new 來執行個體化一個類時,每執行一次迴圈,一個新的object就會被建立,除非你在迴圈體裡回收這個object,否則object將一直駐留在記憶體裡。
注意:
下面代碼是個指令碼例子,提供了處理這個問題方法的說明。你可以使用這個指令碼,但是要自己承擔風險。以執行為目的使這個例子,指令碼必須明確規定了如下所示。產品支援無法自訂此指令碼的具體環境或應用程式。
迴圈使用Recycle()和積極記憶體回收的例子:
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();
}
}
}