我同時使用LDAP連接該上下文調用close()
並未將其返回到池池,儘管文檔sayingotherwise注意到。因此,當我試圖從池中獲取物品時,它已經達到其最大尺寸,它會掛起。爲什麼不DirContext.close()返回到連接池的LDAP連接?
我設法將它縮小到最小的情況下。儘管我相信我確定地調用了所有相關對象上的close()
,但似乎依靠垃圾回收來實際返回對象到池中,這是意想不到的。 這是怎麼發生的?還有其他一些物品我應該關閉嗎?
在下面的代碼片段:
- 我人爲地設置最大池大小爲1,以突出的問題。
- 我從池中得到
DirContext
(線(2)),試圖將其返回到池(線(4)),然後從池中獲取另一個(線(6)),其應該返回相同的,返回的對象。 - 代替,第二請求(線(6))掛在一些內部呼叫到
Object.wait()
。我猜測它正在等待一個混合對象變得可用。 - 如果通過註釋掉關閉池(1),它不會掛起(但我想要池化!)。
- 如果我註釋掉(3) - 以
SearchResults.next()
通話 - 它工作正常。 - 如果我去掉線(5),以迫使「迴歸池」的呼叫,並請求一個新的對象池之間的垃圾收集,它不掛。
由於註釋掉行(3)使問題消失,也許我沒有正確關閉它的返回值,並且它保持打開的池連接。但是,在這種情況下,方法results.next()
返回SearchResult
,該方法沒有close
方法,在其文檔中沒有關於如何完全關閉它的指導。
測試用例:
@Test
public void testHangs() throws NamingException {
System.setProperty("com.sun.jndi.ldap.connect.pool.debug", "fine");
System.setProperty("com.sun.jndi.ldap.connect.pool.maxsize", "1");
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_PRINCIPAL, user);
env.put(Context.SECURITY_CREDENTIALS, passwd);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.PROVIDER_URL, ldapUrl);
// use a connection pool
env.put("com.sun.jndi.ldap.connect.pool", "true"); // ----------------- (1)
// get a context from the pool.
DirContext context = new InitialDirContext(env); // -------------------- (2)
NamingEnumeration<SearchResult> results = context.search("", query, getSC());
// obviously the next two lines would normally be in a
// while(results.hasMore()) { ... = results.next(); } loop.
assertTrue(results.hasMore()); // this is only a problem when there are some results.
results.next(); // ----------------------------------------------------- (3)
// ensure the context is returned to the pool.
results.close();
context.close(); // ---------------------------------------------------- (4)
//System.gc(); // ------------------------------------------------------ (5)
new InitialDirContext(env); // hangs here! ---------------------------- (6)
}
用,因爲它是代碼,我的控制檯顯示:
Create [email protected][ldapad:389]
Use [email protected]
而如果我強迫GC我還看到:
Release [email protected] <-- on GC
Use [email protected] <-- on new InitialDirContext
謝謝!令人感到沮喪的是,爲了讓LDAP提供者正確管理池連接,您必須努力在不再需要的上下文上調用Context.close(),但並未解釋如何有意義地執行這也不告訴你哪些提供的對象可能自己抓住這些也需要關閉的對象。 – bacar 2012-08-15 09:53:36
如果繼續循環直到'results.next()'返回false,連接會自動關閉。 – EJP 2015-01-15 17:39:21