Утечка памяти в шаблоне Spring jdbc в самом простом приложении - PullRequest
1 голос
/ 21 сентября 2011

У меня есть приложение Spring mvc и Tomcat 7.0.21 в качестве контейнера сервлета.
И когда я пытаюсь использовать 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 при каждом повторном развертывании приложения.

Конечно, я могу просто перезапуститьмой рабочий сервер каждый раз, когда я хочу
повторно развернуть мое приложение, но я хочу выяснить, что не так.


PS: реализация источника данных:

@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;
    }
}

Ответы [ 2 ]

2 голосов
/ 21 сентября 2011

Отмена регистрации драйверов JDBC должна обрабатываться для вас источником данных. См. этот связанный вопрос . Так что проверьте новую версию реализации вашего источника данных. BasicDataSource - не лучший вариант для источника данных. Попробуйте использовать c3p0 и посмотрите, воспроизводится ли проблема.

Даже если это не так, Tomcat прояснит это для вас. Кстати, обновите и своего кота - в последней версии улучшено DriverManager утечек.

Итак, проблема PermGen лежит в другом месте. Это давно известная проблема с tomcat, но они утверждают, что это утечка кода приложения. И это в основном верно, но трудно отследить то, что остается незарегистрированным. Tomcat пытается выяснить общие причины проблемы PermGen, но не может охватить все.

1 голос
/ 21 сентября 2011

Я не думаю, что это связано с JDBCTemplate - это связано с драйвером.Даже если вы делаете DataSource.getConnection, вы должны увидеть те же результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...