在Java Bean中回收Domino对象的最佳方法是什么?

时间:2012-06-22 15:35:51

标签: xpages

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

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对象时,我应该回收数据库和View对象吗?或者应该在函数返回Document之前回收它们?

3 个答案:

答案 0 :(得分:21)

最佳做法是在创建它们的范围内回收所有Domino对象。但是,回收任何对象会自动回收“下方”的所有对象。因此,在您的示例方法中,无法回收wDb,因为这会导致wDoc被回收,因此您将返回一个回收的Document句柄。

因此,如果您想确保不泄漏内存,最好以相反的顺序回收对象(例如,首先是文档,然后是视图,然后是数据库)。这往往需要构建您的方法,以便您可以使用任何方法获取/使用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中,我们在首次使用时声明变量,而不是Table of Contents样式。但是使用Domino对象时,最好还原为TOC,以便无论是否抛出异常,我们都可以尝试在完成后回收它们...因此最终使用它。
  • 返回Object(应该是项目值,而不是文档本身)也在TOC中声明,因此我们可以在方法结束时返回该Object - 再次,无论是否遇到异常(如果有一个例外,可能它仍然是空的。)
  • 此示例调用一个实用程序方法,该方法允许我们将所有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对象。

答案 1 :(得分: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对象

答案 2 :(得分:0)

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

我编写了一个类,其中包含Java Date,String和Doubles的HashMap,项目名称为关键字。所以现在我有一个可序列化的文档表示,加上原始文档noteID,以便在不再需要它时可以快速找到并修改/删除。

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

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

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

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