7

我使用一个函数来访问配置文档:

private Document lookupDoc(String key1) {
    try {
        Session sess = ExtLibUtil.getCurrentSession();
        Database wDb = sess.getDatabase(sess.getServerName(), this.dbname1);
        View wView = wDb.getView(this.viewname1);
        Document wDoc = wView.getDocumentByKey(key1, true);
        this.debug("Got a doc for key: [" + key1 + "]");
        return wDoc;
    } catch (NotesException ne) {
        if (this.DispLookupErrors)
            ne.printStackTrace();
        this.lastErrorMsg = ne.text;
        this.debug(this.lastErrorMsg, "error");
    }
    return null;
}

在另一种方法中,我使用此函数来获取文档:

Document wDoc = this.lookupDoc(key1);

if (wdoc != null) {
    // do things with the document
    wdoc.recycle();
}

回收 Document 对象时是否应该回收 Database 和 View 对象?还是应该在函数返回文档之前回收它们?

4

3 回答 3

21

最佳实践是在创建对象的范围内回收所有 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 对象。

于 2012-06-22T17:07:03.163 回答
0

这是我正在尝试的一个想法。蒂姆的回答非常好,但是对我来说,我确实需要将文档用于其他目的,所以我尝试了这个..

Document doc = null;
            View view = null;
            try {
                Database database = ExtLibUtil.getCurrentSessionAsSigner().getCurrentDatabase();
                view = database.getView("LocationsByLocationCode");
                doc = view.getDocumentByKey(code, true);
                //need to get this via the db object directly so we can safely recycle the view
                String id = doc.getNoteID();
                doc.recycle();
                doc = database.getDocumentByID(id);

            } catch (Exception e) {
                log.error(e);
            } finally {
                JSFUtils.incinerate(view);
            }
            return doc;

然后,您必须确保在调用此方法的任何方法中安全地回收 doc 对象

于 2015-01-02T09:52:29.317 回答
0

我有一些临时文档作为配置文档存在了一段时间,然后不再需要,所以被删除。这是由现有的 Notes 客户端应用程序强制执行的:它们必须存在才能保持快乐。

我编写了一个类,它具有 Java 日期、字符串和双精度的 HashMap,项目名称作为键。所以现在我有了文档的可序列化表示,加上原始文档 noteID,以便在不再需要时可以快速找到并修改/删除它。

这意味着可以收集配置文档,标准例程为 Java 表示创建所有项目的映射,同时考虑项目类型。然后可以立即回收 doc 对象。

返回对象是文档的 Java 类表示,getValue(String name)其中setValue(String name, val)val 可以是 Double String 或 Date。注意:这个结构不需要富文本或附件,所以它保持简单的字段值。

它运作良好,但如果配置文档有很多项目,这可能意味着在内存中不必要地保存大量信息。但在我的特殊情况下并非如此。

关键是:Java 对象现在是可序列化的,因此它可以保留在内存中,并且正如 Tim 出色的回复所暗示的那样,可以立即回收该文档。

于 2018-05-08T16:35:09.790 回答