使用JNDI / LDAP过时套接字连接泄漏

时间:2016-03-31 10:48:30

标签: java memory-leaks ldap jndi

我目前正在审查Oracle的示例如何通过LDAP从目录服务器返回的Java / JNDI中的manually follow referrals(案例throw)。有问题的示例源代码可以下载here

有问题的代码:

// Set up environment for creating initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY, 
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:489/o=JNDITutorial");

// Set referral property to throw ReferralException
env.put(Context.REFERRAL, "throw");

try {
    // Create initial context
    DirContext ctx = new InitialDirContext(env);

    // Set controls for performing subtree search
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    // Do this in a loop because we don't know how
    // many referrals there will be
    for (boolean moreReferrals = true; moreReferrals;) {
    try {
        // Perform search
        NamingEnumeration answer = ctx.search("", "(objectclass=*)", 
        ctls);

        // Print the answer
        while (answer.hasMore()) {
        System.out.println(">>>" + 
            ((SearchResult)answer.next()).getName());
        }

        // search completes with no more referrals
        moreReferrals = false;

    } catch (ReferralException e) {

        if (! followReferral(e.getReferralInfo())) {
        moreReferrals = e.skipReferral();
        }

        // point to the new context
        if (moreReferrals) {
        ctx = (DirContext) e.getReferralContext();
        }
    }
    }

    // Close the context when we're done
    ctx.close();
} catch (NamingException e) {
    e.printStackTrace();
}

我认为这段代码在几个方面存在缺陷。 DirContextNamingEmuneration的文档显示了close方法,它会立即释放资源。特别是前者拥有一个到目标服务器的开放套接字。不关闭它会导致插座泄漏。

我对代码的理解(缺陷)是:

  1. NamingEnumeration answer永远不会关闭。
  2. DirContext的情况下,未关闭的第一个NamingException应移至finally块。
  3. 使用DirContext覆盖e.getReferralContext()创建的ctx表示中间推介以及InitialDirContext永远不会关闭并导致泄密。
  4. 我的发现是否正确?

    PS:在设置follow的情况下,我也检查了Oracle的内部实现,有趣的是所有推荐上下文都在内部关闭。

    免责声明:我最初在Code Review发布了这封信,但由于它不是我的代码而被关闭了。我被建议尝试SO。

1 个答案:

答案 0 :(得分:2)

您需要关闭NamingEnumeration,以及从JNDI获得的任何其他可关闭的内容。