简体   繁体   English

使用JNDI / LDAP的陈旧套接字连接泄漏

[英]Stale socket connection leak with JNDI/LDAP

I am currently reviewing Oracle's examples how to manually follow referrals (case throw ) in Java/JNDI returned from a directory server via LDAP. 我目前正在查看Oracle的示例,该示例如何手动遵循通过LDAP从目录服务器返回的Java / JNDI中的引用 (case throw )。 The example source code in question can be downloaded here . 有问题的示例源代码可以在此处下载。

The code in question: 有问题的代码:

// 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();
}

I consider this code flawed in several ways. 我认为此代码在几种方面存在缺陷。 The documentation of DirContext and NamingEmuneration exibit a close method wich immediately releases resources. DirContextNamingEmuneration的文档证明使用close方法可以立即释放资源。 Especially the former holds an open socket to the target server. 特别是前者持有目标服务器的开放套接字。 Not closing it will lead to a socket leakage. 不关闭它会导致插座泄漏。

My understanding (flaws) of the code is: 我对代码的理解(缺陷)是:

  1. NamingEnumeration answer is never closed. NamingEnumeration answer永远不会关闭。
  2. The very first DirContext in not closed in the case of a NamingException , should be moved to a finally block. 如果发生NamingException ,则第一个DirContext未关闭,应将其移动到finally块。
  3. The DirContext created with e.getReferralContext() overwrite ctx which means that intermediate referrals as well as the InitialDirContext are never closed and lead to leak. 使用e.getReferralContext()创建的DirContext覆盖ctx ,这意味着中间引用以及InitialDirContext永远不会关闭并导致泄漏。

Are my findings correct? 我的发现正确吗?

PS: I have also checked Oracle's internal implemenation in the case that follow is set and the funny thing is all referral contexts are closed internally. PS:我还检查Oracle内部实行在该情况下, follow设定和有趣的是所有转诊上下文内部封闭。

Disclaimer: I have posted this initially on Code Review but it was closed because it is not my code. 免责声明:我最初将其发布在Code Review上,但由于它不是我的代码,因此已关闭。 I was advised to try on SO. 建议我尝试SO。

您需要关闭NamingEnumeration以及从JNDI获得的其他任何可关闭的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM