最佳实践是在创建对象的范围内回收所有 Domino 对象。但是,回收任何对象会自动回收它“下方”的所有对象。因此,在您的示例方法中,您不能回收 wDb,因为这会导致 wDoc 也被回收,因此您将返回一个回收的 Document 句柄。
因此,如果您想确保没有泄漏内存,最好以相反的顺序回收对象(例如,首先是文档,然后是视图,然后是数据库)。这往往需要结构化您的方法,以便您在任何方法获得句柄的情况下对 Domino 对象执行所需的操作/使用 Domino 对象。
例如,我假设您定义获取配置文档的方法的原因是您可以从中提取配置设置的值。因此,与其使用返回文档的方法,不如定义一个返回项目值的方法:
private Object lookupItemValue(String configKey, itemName) {
Object result = null;
Database wDb = null;
View wView = null;
Document wDoc = null;
try {
Session sess = ExtLibUtil.getCurrentSession();
wDb = sess.getDatabase(sess.getServerName(), this.dbname1);
wView = wDb.getView(this.viewname1);
wDoc = wView.getDocumentByKey(configKey, true);
this.debug("Got a doc for key: [" + configKey + "]");
result = wDoc.getItemValue(itemName);
} catch (NotesException ne) {
if (this.DispLookupErrors)
ne.printStackTrace();
this.lastErrorMsg = ne.text;
this.debug(this.lastErrorMsg, "error");
} finally {
incinerate(wDoc, wView, wDb);
}
return result;
}
上面有几点值得解释:
- 通常在 Java 中,我们在第一次使用时声明变量,而不是目录样式。但是对于 Domino 对象,最好恢复到 TOC,这样无论是否抛出异常,我们都可以在完成后尝试回收它们……因此使用 finally。
- 返回对象(应该是一个项目值,而不是文档本身)也在 TOC 中声明,因此我们可以在方法结束时返回该对象 - 同样,无论是否遇到异常(如果有异常,大概它仍然是空的)。
- 此示例调用一个实用方法,该方法允许我们将所有 Domino 对象传递给单个方法调用以进行回收。
这是该实用程序方法的代码:
private void incinerate(Object... dominoObjects) {
for (Object dominoObject : dominoObjects) {
if (null != dominoObject) {
if (dominoObject instanceof Base) {
try {
((Base)dominoObject).recycle();
} catch (NotesException recycleSucks) {
// optionally log exception
}
}
}
}
}
它是私有的,因为我假设您将在同一个 bean 中定义它,但最近我倾向于将其定义为 Util 类的公共静态方法,允许我在几乎任何地方遵循相同的模式。
最后一点:如果您要从配置文档中检索大量项目值,显然为您想要返回的每个项目值建立一个新的数据库、视图和文档句柄会很昂贵。因此,我建议重写此方法以接受项目名称的 List<String>(或 String[])并返回结果值的 Map<String, Object>。这样,您可以为数据库、视图和文档建立一个句柄,检索您需要的所有值,然后在实际使用返回的项目值之前回收 Domino 对象。