我目前正在审查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();
}
我认为这段代码在几个方面存在缺陷。 DirContext
和NamingEmuneration
的文档显示了close
方法,它会立即释放资源。特别是前者拥有一个到目标服务器的开放套接字。不关闭它会导致插座泄漏。
我对代码的理解(缺陷)是:
answer
永远不会关闭。DirContext
的情况下,未关闭的第一个NamingException
应移至finally
块。DirContext
覆盖e.getReferralContext()
创建的ctx
表示中间推介以及InitialDirContext
永远不会关闭并导致泄密。我的发现是否正确?
PS:在设置follow
的情况下,我也检查了Oracle的内部实现,有趣的是所有推荐上下文都在内部关闭。
免责声明:我最初在Code Review发布了这封信,但由于它不是我的代码而被关闭了。我被建议尝试SO。
答案 0 :(得分:2)
您需要关闭NamingEnumeration,以及从JNDI获得的任何其他可关闭的内容。