Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
 Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Всем привет!

CentOs7 + Tomcat8 + MariaDB10

Web приложение крутится на Tomcat и пишет в MariaDB через HikariCP.
При остановке приложения я закрываю HikariCP через метод close(). Сами соединения не закрываю.
В результате в логе Tomcat получаю предупреждения:
INFO | HikariPool-1 - Starting...
 INFO | HikariPool-1 - Start completed.
 INFO | HikariPool-1 - Shutdown initiated...
 INFO | HikariPool-1 - Shutdown completed.
 INFO | JMS connection closeed successfully
29-Jul-2019 14:10:53.306 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
29-Jul-2019 14:10:53.306 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
29-Jul-2019 14:10:53.342 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
29-Jul-2019 14:10:53.364 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
29-Jul-2019 14:10:53.379 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [scjmsconsumer] registered the JDBC driver [org.mariadb.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.
29-Jul-2019 14:10:53.395 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer] appears to have started a thread named [MariaDb-bulk-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
 java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:924)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)
29 июл 19, 14:31    [21936875]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Соединения открываются через try-with-resources
29 июл 19, 14:48    [21936902]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
Ну собственно томкат сам пытается подчистить лики, о чем и пишел в лог.
Чтобы проверить получилось ли у него или нет - надо задеплоить томкат, открыть jVisualVM прочекать память, предварительно запустив сборку мусора, потом наживую передеплоить томкат, опять собрать мусор и сравнить объем памяти. Если он +- такой же - значит волноваться не стоит, если в 2 раза больше - значит лик есть.
29 июл 19, 15:27    [21936932]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Как в jVisualVM предварительно запустить сборку мусора?
забыл ник,
29 июл 19, 15:38    [21936940]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
я имею ввиду после того как приложение задеплоилось сделай сборку мусора, чтобы понять сколько оно памяти ест, и тоже самое после редеплоя. А запустить ее надо нажав на кнопку Perform GC если не изменяет память
29 июл 19, 16:22    [21936991]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Kachalov
Member

Откуда: Москва
Сообщений: 5671
Molasar, все написано в сообщении:
Molasar
registered the JDBC driver ... To prevent a memory leak, the JDBC Driver has been forcibly unregistered


- смысл: либо используйте JDBC-пул настроенный в Tomcat (тогда он сам будет анрегистерить драйвер), либо делайте это в своем коде сами (еще ни разу не видел чтобы кто то это делал). Иначе будет течь память (при каждом старте приложения драйвер регистрируется заново, а при стопе не арегистрится).
29 июл 19, 16:28    [21936999]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9430
Molasar
Web приложение крутится на Tomcat и пишет в MariaDB через HikariCP.
При остановке приложения я закрываю HikariCP через метод close(). Сами соединения не закрываю.
В результате в логе Tomcat получаю предупреждения:
Перенесите jdbc-драйвера и, вероятно, HikariCP из контекста приложения в ${CATALINA.BASE}/lib
29 июл 19, 18:00    [21937136]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Скопировал.
В в каталоге приложения WEB-INF\lib их нужно удалить?
Как собрать war без зависимостей?
Basil A. Sidorov
Molasar
Web приложение крутится на Tomcat и пишет в MariaDB через HikariCP.
При остановке приложения я закрываю HikariCP через метод close(). Сами соединения не закрываю.
В результате в логе Tomcat получаю предупреждения:
Перенесите jdbc-драйвера и, вероятно, HikariCP из контекста приложения в ${CATALINA.BASE}/lib
31 июл 19, 12:47    [21938785]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Переносом драйвера JDBC из контекста приложения в ${CATALINA.BASE}/lib я избавился от предупреждения failed to unregister it when the web application was stopped.
При этом в POM я добавил <scope>runtime</scope> для mariadb-java-client

Но при этом остаются предупреждения:
31-Jul-2019 14:14:47.699 WARNING [http-nio-8080-exec-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer-0.0.1] appears to have started a thread named [MariaDb-bulk-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
 java.util.concurrent.SynchronousQueue.poll(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)
31-Jul-2019 14:14:47.702 WARNING [http-nio-8080-exec-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer-0.0.1] appears to have started a thread named [MariaDb-bulk-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
 java.util.concurrent.SynchronousQueue.poll(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)
31-Jul-2019 14:14:47.703 WARNING [http-nio-8080-exec-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer-0.0.1] appears to have started a thread named [MariaDb-bulk-3] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
 java.util.concurrent.SynchronousQueue.poll(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)
31-Jul-2019 14:14:47.704 WARNING [http-nio-8080-exec-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer-0.0.1] appears to have started a thread named [MariaDb-bulk-4] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
 java.util.concurrent.SynchronousQueue.poll(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)
31-Jul-2019 14:14:47.705 WARNING [http-nio-8080-exec-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer-0.0.1] appears to have started a thread named [MariaDb-bulk-5] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
 java.util.concurrent.SynchronousQueue.poll(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)
31-Jul-2019 14:14:47.707 WARNING [http-nio-8080-exec-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [scjmsconsumer-0.0.1] appears to have started a thread named [MariaDb-bulk-6] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
 java.util.concurrent.SynchronousQueue.poll(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)

После остановки приложения потоки MariaDb-bulk остаются припаркованными в памяти. Как их закрыть?

К сообщению приложен файл. Размер - 114Kb
31 июл 19, 14:22    [21938925]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9430
Жизненный цикл сервлета предусматривает методы init() и destroy().
В первом инициализируете подключение к базе при развертывании (старте) контекста приложения, во втором - "прибираетесь" при "свёртывании".
Учитываете, что в обоих методах не должно быть "долгоиграющих" действий и что один и тот же сервлет может работать в нескольких контекстах: static и прочая "глобализация" только там, где вы точно понимаете, что именно вы делаете.
31 июл 19, 14:39    [21938948]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Ниже простейший пример, который вызывает это предупреждение:
WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ConnTest2] appears to have started a thread named [MariaDb-bulk-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
Причем припаркованные, но не завершенные, потоки MariaDB-bulk возникают при использовании statement.executeBatch().
Всё закрыто, всё прибрано.
@WebListener
public class CTServletContextListener implements ServletContextListener {

    private static HikariDataSource hikariDataSource;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        hikariDataSource = new HikariDataSource(getHikariConfig());
        
        try (Connection connection = hikariDataSource.getConnection();
                Statement statement = connection.createStatement()) {
            statement.addBatch("insert into mytab1 (id) values (1)");
            statement.executeBatch();
            connection.commit();
        } catch (SQLException ex) {
            Logger.getLogger(CTServletContextListener.class
                    .getName()).log(Level.SEVERE, null, ex);
        }
        
        hikariDataSource.close();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }

    private HikariConfig getHikariConfig() {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl("jdbc:mariadb://192.168.0.158:3306/scjmsdb");
        hikariConfig.setUsername("user");
        hikariConfig.setPassword("user");
        hikariConfig.setDriverClassName("org.mariadb.jdbc.Driver");
        return hikariConfig;
    }

Basil A. Sidorov
Жизненный цикл сервлета предусматривает методы init() и destroy().
В первом инициализируете подключение к базе при развертывании (старте) контекста приложения, во втором - "прибираетесь" при "свёртывании".
Учитываете, что в обоих методах не должно быть "долгоиграющих" действий и что один и тот же сервлет может работать в нескольких контекстах: static и прочая "глобализация" только там, где вы точно понимаете, что именно вы делаете.
31 июл 19, 17:49    [21939185]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9430
Molasar
Всё закрыто, всё прибрано.
try (Connection connection = hikariDataSource.getConnection();
  Statement statement = connection.createStatement()) {
  statement.addBatch("insert into mytab1 (id) values (1)");
  statement.executeBatch();
  connection.commit();
}
Не похоже на try-с-ресурсом.
дока Java SE API
java.sql
Interface Statement
All Superinterfaces: AutoCloseable, Wrapper
Поэтому напрашивается:
try ( Connection connection = hikariDataSource.getConnection() ) {
  try ( Statement statement = connection.createStatement() ) {
    // работаем работу
  }
}
31 июл 19, 18:35    [21939225]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Molasar
Member

Откуда:
Сообщений: 767
Вот работающий вариант с одним try-с-ресурсом:
        try (Connection connection = DriverManager.getConnection(connUrl);
                Statement statement = connection.createStatement()) {
            statement.addBatch("insert into mytab1 (id) values (1)");
            statement.executeBatch();
            connection.commit();
        } catch (SQLException ex) {
            Logger.getLogger(CTServletContextListener.class
                    .getName()).log(Level.SEVERE, null, ex);
        }

И в моём и в вашем вариантах всё равно появляется предупреждение.
Так что дело в другом...((((

Basil A. Sidorov
Molasar
Всё закрыто, всё прибрано.
try (Connection connection = hikariDataSource.getConnection();
  Statement statement = connection.createStatement()) {
  statement.addBatch("insert into mytab1 (id) values (1)");
  statement.executeBatch();
  connection.commit();
}
Не похоже на try-с-ресурсом.
дока Java SE API
java.sql
Interface Statement
All Superinterfaces: AutoCloseable, Wrapper
Поэтому напрашивается:
try ( Connection connection = hikariDataSource.getConnection() ) {
  try ( Statement statement = connection.createStatement() ) {
    // работаем работу
  }
}
1 авг 19, 09:54    [21939530]     Ответить | Цитировать Сообщить модератору
 Re: Tomcat: предупреждение об утечке памяти  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9430
Molasar
И в моём и в вашем вариантах всё равно появляется предупреждение.
Значит читайте доки Hikari и MariaDB.
1 авг 19, 12:46    [21939745]     Ответить | Цитировать Сообщить модератору
Все форумы / Java Ответить