我有spring mvc应用程序和Tomcat 7.0.21作为servlet容器
当我在我的应用程序中尝试使用jdbcTemplate时,它无法正确重新部署 -
它可以防止jvm清理PermGen内存
坏代码的简单示例如下
(当然为了简单起见打破mvc概念):
@Controller
class MainController {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@RequestMapping("/")
public String mainPage() {
jdbcTemplate.queryForObject("SELECT val FROM tbl WHERE id=1",
String.class);
return "main";
}
}
没有jdbcTemplate.queryForObject(...)
它完美无缺,但是
在部署到tomcat时,它会说:
Sep 21, 2011 1:54:38 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/my] 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.
Sep 21, 2011 1:54:38 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/my] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak.
之后我可以在VisualVM中看到每次重新部署应用程序时PermGen的增长。
当然,每次我想要时,我都可以重启我的生产服务器
重新部署我的应用程序,但我想弄明白什么是错误的。
P.S。:数据源实施:
@Configuration
public class ApplicationConfig {
@Bean
DataSource dataSource(@Value("${jdbc.driver}") String driver,
@Value("${jdbc.url}") String url, @Value("${jdbc.user}") String user,
@Value("${jdbc.password}") String password) {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(password);
return ds;
}
}
答案 0 :(得分:2)
数据源应该为您处理取消注册JDBC驱动程序。见this related question。因此,请检查数据源实现的较新版本。 BasicDataSource
不是数据源的最佳选择。尝试使用c3p0并查看是否重现了问题。
即使不是,Tomcat也会为你清除。顺便说一句,升级你的tomcat - 它在最新版本中对DriverManager
泄漏有所改进。
因此,PermGen问题存在于其他地方。对于tomcat来说,这是一个众所周知的问题,但他们声称它是泄漏的应用程序代码。这基本上是正确的,但很难跟踪未注册的内容。 Tomcat尝试清除PermGen问题的常见原因,但不能涵盖所有内容。
答案 1 :(得分:1)
我不认为这是由于JDBCTemplate - 它是由驱动程序引起的。即使您执行DataSource.getConnection,您也应该看到相同的结果。