JNDI/LDAP 的陈旧套接字连接泄漏
Stale socket connection leak with JNDI/LDAP
我目前正在查看 Oracle 的示例如何 manually follow referrals (case throw
) in Java/JNDI returned from a directory server via LDAP. The example source code in question can be downloaded 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();
}
我认为这段代码在几个方面存在缺陷。 DirContext
和 NamingEmuneration
的文档展示了一个 close
立即释放资源的方法。特别是前者持有到目标服务器的开放套接字。不关闭它会导致套接字泄漏。
我对代码的理解(缺陷)是:
- NamingEnumeration
answer
永远不会关闭。
- 在
NamingException
的情况下,第一个 DirContext
未关闭,应移至 finally
块。
- 用
e.getReferralContext()
创建的 DirContext
覆盖 ctx
这意味着中间引用以及 InitialDirContext
永远不会关闭并导致泄漏。
我的发现是否正确?
PS:我还检查了 Oracle 在设置 follow
的情况下的内部实现,有趣的是所有引用上下文都在内部关闭。
免责声明:我最初在 Code Review 上发布了此内容,但由于不是我的代码而被关闭。有人建议我试试 SO。
您需要关闭 NamingEnumeration,以及您从 JNDI 获得的任何其他可关闭的东西。
我目前正在查看 Oracle 的示例如何 manually follow referrals (case throw
) in Java/JNDI returned from a directory server via LDAP. The example source code in question can be downloaded 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();
}
我认为这段代码在几个方面存在缺陷。 DirContext
和 NamingEmuneration
的文档展示了一个 close
立即释放资源的方法。特别是前者持有到目标服务器的开放套接字。不关闭它会导致套接字泄漏。
我对代码的理解(缺陷)是:
- NamingEnumeration
answer
永远不会关闭。 - 在
NamingException
的情况下,第一个DirContext
未关闭,应移至finally
块。 - 用
e.getReferralContext()
创建的DirContext
覆盖ctx
这意味着中间引用以及InitialDirContext
永远不会关闭并导致泄漏。
我的发现是否正确?
PS:我还检查了 Oracle 在设置 follow
的情况下的内部实现,有趣的是所有引用上下文都在内部关闭。
免责声明:我最初在 Code Review 上发布了此内容,但由于不是我的代码而被关闭。有人建议我试试 SO。
您需要关闭 NamingEnumeration,以及您从 JNDI 获得的任何其他可关闭的东西。