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);
}
}
java 数据库连接 释放_java - 数据库连接池耗尽 - Java - 堆栈内存溢出相关推荐
- Java页码超出_java - 表中的页码 - 堆栈内存溢出
为此,创建一个文本运行,并在这些文本运行中插入字段"PAGE \\\\* MERGEFORMAT"和/或"NUMPAGES \\\\* MERGEFORMAT" ...
- java soap附件_java - 附件在SoapUI中工作,但在Java中不能使用SAAJ API吗? - 堆栈内存溢出...
我能够使用SoapUI附加一个完全相同的SOAP Request的zip文件,但不能使用SAAJ Api的Java. 这是我在SOAPUI和JAVA中使用的SOAP请求: projectName ci ...
- java中pack函数_java - Java函数pack(),JFrame大小 - 堆栈内存溢出
我在使用函数pack()时遇到了一些问题,因为我知道它应该将JFrame的大小设置为最小. 这是我的杰作: import java.awt.*; import java.awt.event.*; im ...
- java光标位置无效_java - java.sql.SQLException:无效的光标位置 - 堆栈内存溢出
我创建了一个简单的应用程序,使用户可以购买门票. 但是,每当我尝试购买" n"张门票时,都会遇到此错误. 现在,我知道在使用数据库进行操作时需要crs.next()语句,我已经使用 ...
- java comparator内部类_java - Java Comparator使用.reverseOrder()但内部类 - 堆栈内存溢出...
我正在创建一个简单的程序来了解Java Comparator类. 我已经按顺序对一个Arraylist了排序,但现在我想按降序对列表进行排序,但是我在调用.reverseOrder()方法时遇到问 ...
- java中方法未定义_java - Java SE中的未定义方法错误 - 堆栈内存溢出
我为该问题写了一个代码http://www.spoj.com/problems/PRIME1/ ,该代码的作用是将输入以字符串形式输入,然后将split()拆分为两个整数,并存储在该数组中.然后返回到 ...
- Java顺序栈的初始化_java - Java类变量初始化的顺序是什么? - 堆栈内存溢出
在Java中,类变量按以下顺序初始化: 超类的静态变量 此类的所有静态变量都设置为其默认值 . 静态变量和静态初始化块,按声明顺序排列. 超类的实例变量 此类的所有实例变量都设置为其默认值 . 声明顺 ...
- java 重载 参数子类_java - Java中带有子类参数的函数重载 - 堆栈内存溢出
这个问题已经在这里有了答案: 我有一个扩展了另一个类的类(在这种情况下,这是一个例外): public class NewTypeException extends Exception { priva ...
- java字符串转语音文件_java - Java文字转语音(Spring Boot) - 堆栈内存溢出
我从事的项目是必须使用SpringBoot生成验证码. 我想要一个"文本到语音"功能,并且声音文件必须使用SpringBoot生成(否则这将是一个巨大的安全问题). 我生成了一个验 ...
最新文章
- mysqldump和xtrabackup备份原理实现说明
- 机器学习让3D设计速度提升7倍!Adobe最新Substance 3D小白也能入门
- idea每次都要配置tomcat_电脑每次开机时间都不对?电脑每次开机都要重新设置时间解决方法...
- Apache Kafka-消费端_顺序消费的实现
- python10的因数_十五道Python小案例,学会这些,Python基础已过关!
- 【HDU - 5452】Minimum Cut(树形dp 或 最近公共祖先lca+树上差分,转化tricks,思维)
- 如何将 MySQL 去重操作优化到极致?| CSDN 博文精选
- Visual Basic 终于要衰落了吗?
- NLP纠错 | 恶意短信变体字还原、鲁棒性过滤与文本纠错竞赛概述与简单变体实现...
- 安卓和ios的ui设计区别_【交互设计】 也许这些才是你作品集最需要的
- 8.22 今日头条笔试
- 十五个免费Windows桌面系统工具(附下载)
- 数据结构与算法实验:实验二 链表实现一元多项式的加法/减法/乘法/求导
- 现场直播:域名转出的黑幕和愤怒!(商务中国BIZCN和美橙互联CNDNS)
- 移动端隐藏scroll滚动条::-webkit-scrollbar
- 知云文献翻译打不开_神器推荐丨知云文献翻译软件 WIN/MAC/IOS/ANDROID/网页版
- NVIDIA GeForce GTX 950M 新出驱动程序
- ChinaSkills技能大赛网络系统管理Debian模块(样题一)||Client配置
- 如何在html中自动播放音乐,如何使音乐在打开页面时自动播放
- 银行股价预测——基于pytorch框架RNN神经网络
热门文章
- Karmada 千级容器集群:工商银行业务容灾管理设计利器
- idea 注释中 类 跳转_javaSE第一部分 数据类型、idea快捷键
- android计算距离顶部的距离,(lua版)计算距离的逻辑是从Android的提供的接口(Location.distanceBetween)中拔来的,应该是最精确的方法了...
- 苹果11是高通基带吗_最强对抗!小米11对抗三星、苹果华为等最高旗舰|喜欢小米吗?...
- java技术简介英文_Java技术常见的英文缩写
- 将你一张表的值覆盖_山西联通携手华为完成长风商务区宏微协同,立体覆盖,打造5G精品网络...
- 二本考北航计算机经历,我(来自二本学校)考上北航的一些经历
- 太原冶金技师学院计算机系,山西冶金技师学院2021年招生简章
- qos的_QoS 概述
- Ambari系统架构