java 數據庫連接 釋放_java - 數據庫連接池耗盡 - Java - 堆棧內存溢出

timeout變量似乎不對應于連接空閑的時間,而是對應于池等待返回新連接或拋出異常的時間(我看了一下這個源代碼 ,不知道是不是已是最新)。 我認為跟蹤“空閑”連接是相當困難的,因為在這種情況下“空閑”真正意味著什么? 您可能希望獲得連接以供以后使用。 所以我想說連接池知道你完成連接的唯一安全方法就是調用close() 。

如果你擔心開發團隊忘記在他們的代碼中調用close() ,有一種技術我在下面描述并且我過去曾經使用過(在我的例子中我們想要跟蹤未閉合的InputStream但概念是相同)。

免責聲明:

我假設連接僅在單個請求期間使用,并且在連續請求期間不跨越。 在后一種情況下,您無法使用下面的解決方案。

您的連接池實現似乎已經使用了與我在下面描述的技術類似的技術(即它已經包裝了連接),所以我不可能知道這是否適用于您的情況。 我沒有測試下面的代碼,我只是用它來描述這個概念。

請僅在您的開發環境中使用它。 在生產中,您應該確信您的代碼已經過測試并且行為正確。

如上所述,主要思想是:我們有一個中心位置(連接池),我們從中獲取資源(連接),我們希望跟蹤我們的代碼是否釋放了這些資源。 我們可以使用一個Web Filter ,它使用一個ThreadLocal對象來跟蹤請求期間使用的連接。 我將此類命名為TrackingFilter ,跟蹤資源的對象是Tracker類。

public class TrackingFilter implements Filter {

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

Tracker.start();

try {

chain.doFilter(request, response);

} finally {

Tracker.stop();

}

}

...

}

為了使Tracker能夠跟蹤連接,每次使用getConnection()獲取連接時以及每次使用close()調用關閉連接時都需要通知它。 為了能夠以對代碼的其余部分透明的方式執行此操作,我們需要包裝ConnectionPool和返回的Connection對象。 您的代碼應該返回新的TrackingConnectionPool而不是原始池(我假設訪問連接池的方式是在一個地方)。 這個新池將依次包裝它提供的每個Connection ,作為TrackableConnection 。 TrackableConnection是知道如何在創建和關閉時通知我們的Tracker的對象。

當您在請求結束時調用Tracker.stop()時,它將報告尚未調用close()所有連接。 由于這是一個按請求操作,您將只識別錯誤操作(即在“創建新產品”功能期間),然后希望您能夠跟蹤那些保留打開連接并修復它們的查詢。

您可以在下面找到TrackingConnectionPool , TrackableConnection和Tracker類的代碼和注釋。 為簡潔起見,遺漏了代表方法。 我希望有所幫助。

注意:對于包裝器使用自動IDE功能(如Eclipse的“生成委托方法”),否則這將是一個耗時且容易出錯的任務。

//------------- Pool Creation

ConnectionPool original = new ConnectionPool(String dbpoolName, ...);

TrackingConnectionPool trackingCP = new TrackingConnectionPool(original);

// ... or without creating the ConnectionPool yourself

TrackingConnectionPool trackingCP = new TrackingConnectionPool(dbpoolName, ...);

// store the reference to the trackingCP instead of the original

//------------- TrackingConnectionPool

public class TrackingConnectionPool extends ConnectionPool {

private ConnectionPool originalPool; // reference to the original pool

// Wrap all available ConnectionPool constructors like this

public TrackingConnectionPool(String dbpoolName, ...) {

originalPool = new ConnectionPool(dbpoolName, ...);

}

// ... or use this convenient constructor after you create a pool manually

public TrackingConnectionPool(ConnectionPool pool) {

this.originalPool = pool;

}

@Override

public Connection getConnection() throws SQLException {

Connection con = originalPool.getConnection();

return new TrackableConnection(con); // wrap the connections with our own wrapper

}

@Override

public Connection getConnection(long timeout) throws SQLException {

Connection con = originalPool.getConnection(timeout);

return new TrackableConnection(con); // wrap the connections with our own wrapper

}

// for all the rest public methods of ConnectionPool and its parent just delegate to the original

@Override

public void setCaching(boolean b) {

originalPool.setCaching(b);

}

...

}

//------------- TrackableConnection

public class TrackableConnection implements Connection, Tracker.Trackable {

private Connection originalConnection;

private boolean released = false;

public TrackableConnection(Connection con) {

this.originalConnection = con;

Tracker.resourceAquired(this); // notify tracker that this resource is aquired

}

// Trackable interface

@Override

public boolean isReleased() {

return this.released;

}

// Note: this method will be called by Tracker class (if needed). Do not invoke manually

@Override

public void release() {

if (!released) {

try {

// attempt to close the connection

originalConnection.close();

this.released = true;

} catch(SQLException e) {

throw new RuntimeException(e);

}

}

}

// Connection interface

@Override

public void close() throws SQLException {

originalConnection.close();

this.released = true;

Tracker.resourceReleased(this); // notify tracker that this resource is "released"

}

// rest of the methods just delegate to the original connection

@Override

public Statement createStatement() throws SQLException {

return originalConnection.createStatement();

}

....

}

//------------- Tracker

public class Tracker {

// Create a single object per thread

private static final ThreadLocal _tracker = new ThreadLocal() {

@Override

protected Tracker initialValue() {

return new Tracker();

};

};

public interface Trackable {

boolean isReleased();

void release();

}

// Stores all the resources that are used during the thread.

// When a resource is used a call should be made to resourceAquired()

// Similarly when we are done with the resource a call should be made to resourceReleased()

private Map monitoredResources = new HashMap();

// Call this at the start of each thread. It is important to clear the map

// because you can't know if the server reuses this thread

public static void start() {

Tracker monitor = _tracker.get();

monitor.monitoredResources.clear();

}

// Call this at the end of each thread. If all resources have been released

// the map should be empty. If it isn't then someone, somewhere forgot to release the resource

// A warning is issued and the resource is released.

public static void stop() {

Tracker monitor = _tracker.get();

if ( !monitor.monitoredResources.isEmpty() ) {

// there are resources that have not been released. Issue a warning and release each one of them

for (Iterator it = monitor.monitoredResources.keySet().iterator(); it.hasNext();) {

Trackable resource = it.next();

if (!resource.isReleased()) {

System.out.println("WARNING: resource " + resource + " has not been released. Releasing it now.");

resource.release();

} else {

System.out.println("Trackable " + resource

+ " is released but is still under monitoring. Perhaps you forgot to call resourceReleased()?");

}

}

monitor.monitoredResources.clear();

}

}

// Call this when a new resource is acquired i.e. you a get a connection from the pool

public static void resourceAquired(Trackable resource) {

Tracker monitor = _tracker.get();

monitor.monitoredResources.put(resource, resource);

}

// Call this when the resource is released

public static void resourceReleased(Trackable resource) {

Tracker monitor = _tracker.get();

monitor.monitoredResources.remove(resource);

}

}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539066.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539066.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539066.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spark DAGScheduler、TaskSchedule、Executor執行task源碼分析

摘要 spark的調度一直是我想搞清楚的東西,以及有向無環圖的生成過程、task的調度、rdd的延遲執行是怎么發生的和如何完成的,還要就是RDD的compute都是在executor的哪個階段調用和執行我們定義的函數的。這些都非常的基礎和困難。花一段時間終于弄白了其中…

一個“老”程序員的思考

本文是一位40歲老程序員對職業生涯的思考,建議多學習接觸新事物,將精力投入到衰竭期比較長的知識領域,這些都是很有建設性的。下面是大意譯文: 我是一個程序員,幾個月前剛過完害羞的四十歲生日。這是一個星期六的早晨…

python socketio_python3--socketIO_client 摸索怕坑指南

前言:websocket和socketIO是全然不同的兩個東西,websocket的話 使用自帶ws的庫就可以完成一些功能,但是socketIO屬于sw的另外一塊內容工作中遇到了一個監控socketIO傳輸的聊天信息監控的需求.研究了一陣 話不多說 上代碼!from socketIO_client import SocketIO, BaseNamespacei…

java正則表達式非貪婪_正則表達式中的貪婪與非貪婪匹配模式

1.首先看看下面的例子:try{str"abcdefgabcdefghijkl";re1str.match(/[\W\w]?/ig);alert("非貪婪模式:\r\n\r\n1:"re1[0]"\r\n2:"re1[1]);re1str.match(/[\W\w]/ig);alert("貪婪模…

python編程運算符號-Python中的邏輯運算符

參考資料:http://blog.csdn.net/sasoritattoo/article/details/12451359 一、邏輯判斷詞not 1.在python中not是邏輯判斷詞,用于布爾型True和False,not True為False,not False為True,以下是幾個常用的not的用法&#xf…

代碼實現tan graph model for classification_自定義 Estimator 實現(以BERT為例)

本文將主要介紹tensorflow 的Estimator 這個高級API,它的主要作用就是提出一個高級范式(paradigm),將模型的訓練,驗證,預測,以及保存規范起來,免去了tensorflow的Session.run 的操作…

Linux查看文件內容

cat 一次性將文件內容全部輸出到控制臺 more 可以翻頁查看 空格:下翻一頁 b:上翻一頁 q:退出 less 可以翻頁查看 空格:下翻一頁 b:上翻一頁 q:退出 向上鍵:上翻一行 向下鍵&#xff1…

刷新頁面微信二維碼圖片隨機換,點擊按鈕自動復制對應微信號

<div style"text-align: center;"> <p style"font-size: 18px;color: rgb(255, 79, 121);">添加微信號</p> <span style"font-size: 18px;margin-left: 10%;" id"cod">jyl88jimei</span><br /> &…

SecureCRT向多個tab窗口發命令

可以利用SecureCRT的 Chat Windows選項Send chat to all tabs來同時在服務器上執行相同的命令&#xff0c;具體步驟如下&#xff1a; 一、首先在SecureCRT里同時打開多個服務器session 二、選擇菜單欄View -->Chat Windows 對號&#xff0c;此時所有服務器連接下方應該有個…

英雄聯盟怎么解除小窗口_英雄聯盟手游怎么加好友_英雄聯盟手游怎么加好友一起玩_資訊...

英雄聯盟手游是騰訊聯合英雄聯盟開發商拳頭開發的英雄聯盟手游。不僅能夠高度還原端游的經典操作和競技體驗&#xff0c;也具有非常多創新的元素&#xff0c;對于英雄聯盟的全球生態布局具有重要意義。英雄聯盟手游游戲中有非常多的英雄可以供玩家選擇&#xff0c;并且擁有排位…

jfinal mysql 配置文件_JFinal 如何將操作日志存入到數據庫中

展開全部操作日志, 也分粗細顆粒.比如常見的 配置JFinal的Handler, 配置LogHandler的處理器&#xff0c;Handler可以接管所有web請求, 這里可以做粗顆粒的處理, 對每一個請62616964757a686964616fe59b9ee7ad9431333365653839求做入庫處理, 如果訪問量大時, 入庫操作做列隊處理就…

快速入門python_一天快速入門 Python

Python 是由Guido Van Rossum在 90 年代早期設計&#xff0c;現在是最常用的編程語言之一。特別是人工智能的火熱&#xff0c;再加之它的語法簡潔且優美&#xff0c;實乃初學者入門AI必備的編程語言。作者 | yuquanle責編 | 屠敏Python基本語法標識符第一個字符必須是英文字母或…

Sonar與jenkins集成

2019獨角獸企業重金招聘Python工程師標準>>> 參考文檔&#xff1a;http://blog.csdn.net/kefengwang/article/details/54377055 一.下載&#xff1a;wget https://fossies.org/linux/misc/sonarqube-7.0.zip 二.配置sonar.properties ## sudo vim /opt/sonarqube-6.…

python變量和常量_5、python的變量和常量

今天看看python的變量和常量&#xff0c;這是python中最基本的兩個概念。首先先說一下解釋器執行Python的過程&#xff1a; python3 C:\test.py1. 啟動python解釋器(內存中)2. 將C:\test.py內容從硬盤讀入內存(這一步與文本編輯器是一樣的)3. 執行讀入內存的代碼如果想要永久…

eplan連接定義點不顯示_EPLAN電氣圖實例--控制柜(控制面板)

EPLAN電氣圖實例--控制柜(控制面板)上期回顧(上期主要畫了硬件的布局圖)&#xff1a;這期主要畫一個控制面板控制柜布局1.0 上期主要做了一個長方形的結構板&#xff0c;里面插入了一個結構盒&#xff0c;然后放置一個HMI的宏(這里是KTP1000&#xff0c;在官網隨便找下就行了)&…

virtualbox安裝android6.0并設置分辨率為1920x1080x32

下載安裝&#xff1a;https://www.cnblogs.com/wynn0123/p/6288344.html 這里我做的是下載android6.0-64bit&#xff0c;然后文件系統只支持ext4 安裝完成之后我的虛擬機名稱是Android6.0 設置分辨率為1920x1080x32&#xff1a;https://my.oschina.net/xldc/blog/290155 首先&a…

python中裝飾器修復技術_python3之裝飾器修復技術@wraps

普通函數def f():"""這是一個用來測試裝飾器修復技術的函數"""print("哈哈哈")if __name__ __main__:print("執行的函數名:", f.__name__)print("函數的注釋:", f.__doc__)# 打印結果執行的函數名: f函數的注釋:…

markdown 語法_markdown特殊語法之上下標

markdown特殊語法之上下標?markdown的基本語法很簡單&#xff0c;百度一下就可以了&#xff0c;有空的話我再轉載一些過來。我想的是平常其實需要用到的一些輸入技巧&#xff0c;特殊用法或者擴展語法&#xff0c;還有一些難點倒是要記錄學習一下。在寫作的時候&#xff0c;大…

oracle安裝向導卡住了_JDK 8 的安裝與配置

一、安裝環節1. 打開網頁https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html2.找到對象的版本 盡量從官網下載(官網可能會比較慢&#xff0c;也可以通過瀏覽器輸入jdk版本號進行下載)官網下載需要注冊一個賬號3.雙擊下載的 exe,如 jdk-8u131-windows…

Error contacting service. It is probably not running.

安裝完zookeeper集群后&#xff0c; [rootzk1 data]# zkServer.sh start JMX enabled by default Using config: /application/zookeeper-3.3.6/bin/../conf/zoo.cfg Starting zookeeper ... STARTED [rootzk1 data]# zkServer.sh status JMX enabled by default Using config…