2009-10-26 55 views
7

我們發現連接未關閉的舊代碼中存在一個錯誤。這是一個簡單的解決方法,但我想知道我們如何去證明它是固定的。可以選擇是否使用連接池。對於池的使用,可以很容易地爲池添加監視,但是當沒有使用連接池時,我們如何跟蹤這些未關閉的孤立連接?它就像其他內存泄漏一樣嗎?如何跟蹤未關閉的孤立JDBC連接?

該錯誤看起來基本上是剪切和粘貼錯誤。我們有一個管理數據庫連接幾類,所以它看起來大致是這樣的:

OurDBConn conn1 = ConnectionManager.getConnection(); 
try { 
    // business logic 
} catch() { 
    // 
} finally { 
    ConnectionManager.returnConnection(conn1); 
} 

/// and then later in the same method 
OurDBConn conn2 = ConnectionManager.getConnection(); 
try { 
    // business logic 
} catch() { 
    // 
} finally { 
    ConnectionManager.returnConnection(conn1); // NOTE Error: conn1 should be conn2 
} 

我不知道爲什麼早期的程序員不只是重新使用原來的連接,但是這就是它是

(開始編輯/附加)

是的,連接代碼也是我們的,所以我可以使用給出的答案。

但是,我不認爲我問正確的問題,雖然下面的答案回答了我問的問題。我不知道什麼是正確的stackoverflow的事情是;問另一個問題,或者編輯這個問題?

我應該問的一個問題是:這些孤立的,未關閉的連接將如何在系統性能中體現出來?另外,由於這些連接對象僅存在於特定方法的範圍內,因此連接是否有資格進行垃圾收集?然後,如果他們被打了招呼,開放連接的影響是什麼?

(編輯完)

+0

我會密切關注這一個,我們在幾個項目中遇到了類似的問題。 – Tenner

+1

爲了記錄,我需要有一個非常好的理由,不要將其轉移到成熟的連接池實現,例如DBCP或C3PO - 如果您有機會 - 也許您應該考慮這樣做? – teabot

回答

7

假定連接管理器也被自己的代碼,你可以存儲的初始化連接在連接管理器中的地圖(帶有堆棧跟蹤一起),然後刪除它們時返回他們。因此,在任何時候,地圖的鍵集都是未返回的連接集合,您可以在地圖中查找該值,以便找到創建它們的有害代碼並從不釋放它們。 (如果連接不是合適的映射鍵,則可以使用某種唯一的ID或連接號或其他 - 實際值與其存在無關)。

然後,只需添加一些適當的方式來訪問這張地圖的需求,你很好。根據您的環境,添加一個將映射內容轉儲到文件的關閉鉤子,和/或添加一個JConsole界面來查找運行代碼中的一組未關閉連接,都可以作爲很好的選擇。

如果連接管理器不是您的代碼,您仍然可能使用方面實現相同的事情。

+0

AOP方法的+1 – teabot

+0

我們使用的連接池做的非常像這樣;我相信它會覆蓋它返回的連接,並跟蹤它們何時被使用。如果某個連接的使用時間超過了我們在配置中指定的一段時間,連接將自動終止,並且連接打開時記錄的堆棧跟蹤將打印到日誌中。 – RMorrisey

0

您可以實現自定義迷你框架或使用exisitng作爲JDBC操作的薄包裝。例如,有一個spring-jdbc模塊(mavenized),其中涵蓋了開發人員提供的所有樣板錯誤代碼。

您可以檢查它的usage examples,看看客戶端代碼沒有初始化/清理!它使用'模板方法'模式,即您只需編寫基本的數據處理,並且不用擔心連接/語句/結果集創建和關閉。所以,不可能首先介紹你所說的問題。