-
Tomcat에서 DBCP 사용할 때 Memory leak개발 2014. 5. 9. 12:40
Problem Domain
registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
- dbcp, boneCP를 사용하던... 에러는 발생한다.
- mySQL, Oracle 관계 없이 에러는 발생한다.
-
JPA(+ Hibernate)를 사용할 때만 에러가 발생한다. (JPA를 사용하지 않을 때는 에러가 발생하지 않는다.): org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean 및 관련 클래스를 등록하여사용할 경우 (나만그런가?)Solve
해결 방법... google.com과 stackoverflow.com에서 방황을...-_-;;
1. DataSource가 Close 되는 시점에 명시적으로 드라이버를 unregister 시켜준다.
- extended BasicDataSource class
public class DisposableBasicDataSource extends BasicDataSource {
@Override
public synchronized void close() throws SQLException {
DriverManager.deregisterDriver(DriverManager.getDriver(url));
super.close();
}
}
- added listener
public class JdbcDriverRegistrationListener implements ServletContextListener {
/**
* Default constructor.
*/
public JdbcDriverRegistrationListener() {
// TODO Auto-generated constructor stub
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent sce) {
/**
* simple
*/
/*
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log.info(String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
log.info(String.format("Error deregistering driver %s", driver), e);
}
}
*/
// ... First close any background tasks which may be using the DB ...
// ... Then close any DB connection pools ...
// Now deregister JDBC drivers in this context's ClassLoader:
// Get the webapp's ClassLoader
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Loop through all drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
// This driver was registered by the webapp's ClassLoader, so deregister it:
try {
log.info("Deregistering JDBC driver {}", driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
log.error("Error deregistering JDBC driver {}", driver, ex);
}
} else {
// driver was not registered by the webapp's ClassLoader and may be in use elsewhere
log.trace("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
}
}
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
}
2. 톰켓 lib 폴더에 jdbc 드라이버 jar를 복사한다.
3. JNDI를 사용한다.
컨테이너 리로드가 필요없는 서버는 상관없음.
톰켓에서만 나는건지 아니면 다른 WAS도 그런건지 잘 모르겠음.
'개발' 카테고리의 다른 글
문자열 한줄씩 읽기 (0) 2014.08.29 Maven Repository 사이트 (0) 2014.08.27 푸시에 대한 기본 개념 - 외부 링크 (0) 2014.04.21 [flex/actionscript] as3 프레임워크 (0) 2014.04.09 [외부] Flex 기반 Vector Drawing Editor (0) 2014.04.08