首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >独立jdbc-池实现内存泄漏

独立jdbc-池实现内存泄漏
EN

Stack Overflow用户
提问于 2012-01-17 23:56:51
回答 1查看 3.9K关注 0票数 3

我正在尝试在一个独立的web应用程序中实现jdbc池(自我包含-不依赖server.xml),这样它就可以移动到可能早于7.0的tomcat安装。

我正在用sourceforge驱动程序(net.sourceforge.jtds.jdbc.Driver)连接到MSSQL

除此错误外,一切都运行良好:

严重: web应用程序/jdbc池似乎已经启动了一个名为[Pool:tomcatConnectionPool1-12524859]的线程,但是没有停止它。这很可能造成内存泄漏。

基于,我确定需要关闭jdbc池数据源。不过,我在那篇文章的最后一行中遇到了麻烦:

If --它是在应用程序上下文中配置的,这意味着当web应用程序停止时,您忘记在连接池上调用DataSource.close。

这是令人困惑的建议,因为javax.sql.DataSource没有close()方法。

为了调用close,必须将其转换为using.的数据源。

如何找出我正在使用的数据源类型,以及它的类在哪里?我能从司机罐子里拿出来吗?

除了使用池的servlet之外,我还使用了一个ServletContextListener,这样我就可以从contextInitialized方法开始使用池连接。我开始添加代码以在此contextDestroyed方法中终止连接,但在问号所在的位置被挂起:

代码语言:javascript
复制
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;

public class JdbcPoolListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent myServletContextEvent) {

        // initialize jdbc-pool datasource to start out with pooled connections 
        try {
            Context myContext = (Context) new InitialContext().lookup("java:comp/env");
            DataSource myDataSource = (DataSource) myContext.lookup("jdbc/db");
            myServletContextEvent.getServletContext().setAttribute("JdbcPool", myDataSource);
        } catch (NamingException e) {
            System.out.println("Error initializing jdbc-pool datasource");
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent myServletContextEvent) {

        // failed attempt to close the data source
        ServletContext myServletContext = myServletContextEvent.getServletContext();
        //DataSource myDataSource = (DataSource) myServletContext.getAttribute("JdbcPool");
        DataSource dataSource = (DataSource)((???) myServletContext.getAttribute(contextAttribute)).getConfiguration().getEnvironment().getDataSource();
        dataSource.close();
        myServletContext.removeAttribute("JdbcPool");

        // deregister JDBC driver to prevent Tomcat 7 from complaining about memory leaks
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                System.out.println(String.format("Deregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                System.out.println(String.format("Error deregistering driver %s", driver));
                e.printStackTrace();
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-01-18 01:24:05

解决了这个问题,我注意到tomcat.jdbc.pool.DataSourceProxy有一个close方法,所以我将数据源转换为一个DataSourceProxy,然后在其上调用close。我现在不再获得日志中的tomcat内存泄漏错误。

解决方案:

代码语言:javascript
复制
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;

import org.apache.tomcat.jdbc.pool.DataSourceProxy;

public class JdbcPoolListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent myServletContextEvent) {

        // initialize jdbc-pool datasource to start out with pooled connections 
        try {
            Context myContext = (Context) new InitialContext().lookup("java:comp/env");
            DataSource myDataSource = (DataSource) myContext.lookup("jdbc/cf");
            myServletContextEvent.getServletContext().setAttribute("JdbcPool", myDataSource);
        } catch (NamingException e) {
            System.out.println("Error initializing jdbc-pool datasource");
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent myServletContextEvent) {

    // close datasource from proxy?
    ServletContext myServletContext = myServletContextEvent.getServletContext();
        DataSourceProxy myDataSource = (DataSourceProxy) myServletContext.getAttribute("JdbcPool");
        myDataSource.close();       
        myServletContext.removeAttribute("JdbcPool");

        // deregister JDBC driver to prevent Tomcat 7 from complaining about memory leaks
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                System.out.println(String.format("Deregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                System.out.println(String.format("Error deregistering driver %s", driver));
                e.printStackTrace();
            }
        }
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8903379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档