最近程序除了点小问题,在多次执行某些操作之后屏幕会没有反应,服务器上很多执行的线程也中止。
这是个很严重的问题,只要执行的任务一多,或者服务器开启事件过长,都会有这个现象。
我们自己写的服务器,支持服务器命令行指令。在服务器不响应时,命令行可以动作,但是exit命令执行时会挂起
分析过程:
1. debug模式启动,找到command line线程,手工中断,发现停留在Object.wait()方法上。
2. 向下看线程堆栈,是apache/common/pool/GenericObjectPool调用,向下是hibernate的ConnectionManager
3. 查看对象池的源码,是因为池子满了,因此等待借出对象return. 说明连接打开后没有释放。
4. 因为我们代码中都是调用spring/hibernate的template或者自动事务,不存在手工打开连接,所以怀疑是哪个工具包出了问题。
5. 首先发现dbcp/pool都不是最新的,换上后无效。 hibernate3.1已经最新了。
6. 复制GenericObjectPool,在borrow和return方法中增加log, 打开connection Manager的log, 排除了所以配对的log外,有非connectionManager打开的连接,没有被归还。
7. debug发现是自动事务结束后,连接池中_numActive没有变化,连接没有关闭,怀疑spring问题,spring1.2.1是正式发行版本。在其网站上发现最新版本是1.2.6,看看新版本的更新说明,搜索到hibernate的修正,有一个正好就是说:修正了针对hibernate3.1的事务管理。
8. 更换为spring 1.2.6后正常,同时在dbcp中加大缺省maxActive数量。缺省为8个。
分析,因为hibernate3.1改变了事务处理方式,老版spring出现连接池泄漏。因为以前一直用的3.1的m版,所以看到正式版出来就直接更新了,没想到有些比较重大的改变。记得当初更新时hibernate annotation当时就不能用,过了几天才出来对应的更新版。
结论:单独的api都是没有问题的,配合起来很可能出问题。因此升级时应该谨慎,采用稳定版本,避免出现不匹配问题~~
浪费一个下午的时间~