我目前正在审查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
方法,该方法立即释放资源。特别是前者持有目标服务器的开放套接字。不关闭它会导致插座泄漏。我对代码的理解(缺陷)是:
NamingEnumeration
answer
永远不会关闭。在
DirContext
情况下未关闭的第一个NamingException
应该移至finally
块。用
DirContext
创建的e.getReferralContext()
覆盖ctx
,这意味着中间引用以及InitialDirContext
永远不会关闭并导致泄漏。我的发现正确吗?
PS:在设置了
follow
的情况下,我还检查了Oracle的内部实现,有趣的是,所有引用上下文都在内部关闭。免责声明:我最初在Code Review上发布了此内容,但由于它不是我的代码,因此已关闭。建议我试一下。
最佳答案
您需要关闭NamingEnumeration以及从JNDI获得的其他可关闭内容。