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);

}

}

java 数据库连接 释放_java - 数据库连接池耗尽 - Java - 堆栈内存溢出相关推荐

  1. Java页码超出_java - 表中的页码 - 堆栈内存溢出

    为此,创建一个文本运行,并在这些文本运行中插入字段"PAGE \\\\* MERGEFORMAT"和/或"NUMPAGES \\\\* MERGEFORMAT" ...

  2. java soap附件_java - 附件在SoapUI中工作,但在Java中不能使用SAAJ API吗? - 堆栈内存溢出...

    我能够使用SoapUI附加一个完全相同的SOAP Request的zip文件,但不能使用SAAJ Api的Java. 这是我在SOAPUI和JAVA中使用的SOAP请求: projectName ci ...

  3. java中pack函数_java - Java函数pack(),JFrame大小 - 堆栈内存溢出

    我在使用函数pack()时遇到了一些问题,因为我知道它应该将JFrame的大小设置为最小. 这是我的杰作: import java.awt.*; import java.awt.event.*; im ...

  4. java光标位置无效_java - java.sql.SQLException:无效的光标位置 - 堆栈内存溢出

    我创建了一个简单的应用程序,使用户可以购买门票. 但是,每当我尝试购买" n"张门票时,都会遇到此错误. 现在,我知道在使用数据库进行操作时需要crs.next()语句,我已经使用 ...

  5. java comparator内部类_java - Java Comparator使用.reverseOrder()但内部类 - 堆栈内存溢出...

    我正在创建一个简单的程序来了解Java Comparator类. 我已经按顺序对一个Arraylist了排序,但现在我想按降序对列表进行排序,但是我在调​​用.reverseOrder()方法时遇到问 ...

  6. java中方法未定义_java - Java SE中的未定义方法错误 - 堆栈内存溢出

    我为该问题写了一个代码http://www.spoj.com/problems/PRIME1/ ,该代码的作用是将输入以字符串形式输入,然后将split()拆分为两个整数,并存储在该数组中.然后返回到 ...

  7. Java顺序栈的初始化_java - Java类变量初始化的顺序是什么? - 堆栈内存溢出

    在Java中,类变量按以下顺序初始化: 超类的静态变量 此类的所有静态变量都设置为其默认值 . 静态变量和静态初始化块,按声明顺序排列. 超类的实例变量 此类的所有实例变量都设置为其默认值 . 声明顺 ...

  8. java 重载 参数子类_java - Java中带有子类参数的函数重载 - 堆栈内存溢出

    这个问题已经在这里有了答案: 我有一个扩展了另一个类的类(在这种情况下,这是一个例外): public class NewTypeException extends Exception { priva ...

  9. java字符串转语音文件_java - Java文字转语音(Spring Boot) - 堆栈内存溢出

    我从事的项目是必须使用SpringBoot生成验证码. 我想要一个"文本到语音"功能,并且声音文件必须使用SpringBoot生成(否则这将是一个巨大的安全问题). 我生成了一个验 ...

最新文章

  1. mysqldump和xtrabackup备份原理实现说明
  2. 机器学习让3D设计速度提升7倍!Adobe最新Substance 3D小白也能入门
  3. idea每次都要配置tomcat_电脑每次开机时间都不对?电脑每次开机都要重新设置时间解决方法...
  4. Apache Kafka-消费端_顺序消费的实现
  5. python10的因数_十五道Python小案例,学会这些,Python基础已过关!
  6. 【HDU - 5452】Minimum Cut(树形dp 或 最近公共祖先lca+树上差分,转化tricks,思维)
  7. 如何将 MySQL 去重操作优化到极致?| CSDN 博文精选
  8. Visual Basic 终于要衰落了吗?
  9. NLP纠错 | 恶意短信变体字还原、鲁棒性过滤与文本纠错竞赛概述与简单变体实现...
  10. 安卓和ios的ui设计区别_【交互设计】 也许这些才是你作品集最需要的
  11. 8.22 今日头条笔试
  12. 十五个免费Windows桌面系统工具(附下载)
  13. 数据结构与算法实验:实验二 链表实现一元多项式的加法/减法/乘法/求导
  14. 现场直播:域名转出的黑幕和愤怒!(商务中国BIZCN和美橙互联CNDNS)
  15. 移动端隐藏scroll滚动条::-webkit-scrollbar
  16. 知云文献翻译打不开_神器推荐丨知云文献翻译软件 WIN/MAC/IOS/ANDROID/网页版
  17. NVIDIA GeForce GTX 950M 新出驱动程序
  18. ChinaSkills技能大赛网络系统管理Debian模块(样题一)||Client配置
  19. 如何在html中自动播放音乐,如何使音乐在打开页面时自动播放
  20. 银行股价预测——基于pytorch框架RNN神经网络

热门文章

  1. Karmada 千级容器集群:工商银行业务容灾管理设计利器
  2. idea 注释中 类 跳转_javaSE第一部分 数据类型、idea快捷键
  3. android计算距离顶部的距离,(lua版)计算距离的逻辑是从Android的提供的接口(Location.distanceBetween)中拔来的,应该是最精确的方法了...
  4. 苹果11是高通基带吗_最强对抗!小米11对抗三星、苹果华为等最高旗舰|喜欢小米吗?...
  5. java技术简介英文_Java技术常见的英文缩写
  6. 将你一张表的值覆盖_山西联通携手华为完成长风商务区宏微协同,立体覆盖,打造5G精品网络...
  7. 二本考北航计算机经历,我(来自二本学校)考上北航的一些经历
  8. 太原冶金技师学院计算机系,山西冶金技师学院2021年招生简章
  9. qos的_QoS 概述
  10. Ambari系统架构