产品: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();
}
}
}