Activiti развернул зарегистрированный драйвер JDBC [org.h2.Driver], но не смог отменить его, когда веб-приложение было остановлено [дублировать]

релиз Android 6.0 (API Level 23) удаляет поддержку для HTTP-клиента Apache. Следовательно, вы не можете использовать эту библиотеку непосредственно в API 23. Но есть способ ее использования. Добавьте useLibrary 'org.apache.http.legacy' в ваш файл build.gradle, как показано ниже -

android {
    useLibrary 'org.apache.http.legacy'
}

Если это не сработает, вы можете применить следующий хак -

- Скопируйте файл org.apache.http.legacy.jar, который находится в каталоге / platform / android-23 / optional вашего каталога Android SDK в папку вашего приложения / libs вашего проекта.

- Теперь добавьте файлы компиляции ('libs /org.apache.http.legacy.jar ') внутри зависимых {} разделов файла build.gradle.

283
задан BalusC 13 October 2011 в 03:07
поделиться

14 ответов

Начиная с версии 6.0.24, Tomcat поставляется с функцией обнаружения утечки памяти , что, в свою очередь, может привести к появлению подобных предупреждающих сообщений, когда в файле [app1] для веб-сервера есть JDBC 4.0-совместимый драйвер, auto- регистрирует сам во время запуска webapp, используя ServiceLoader API , но который сам не отключился deregister во время отключения Webapp. Это сообщение является чисто неофициальным, Tomcat уже принял меры по предотвращению утечки памяти.

Что вы можете сделать?

  1. Игнорировать эти предупреждения. Tomcat делает свою работу правильно. Фактическая ошибка находится в чужом коде (именно драйвер JDBC), а не в вашем. Будьте счастливы, что Tomcat выполнил свою работу должным образом и дождитесь, пока поставщик драйверов JDBC зафиксирует это, чтобы вы могли обновить драйвер. С другой стороны, вы не должны бросать JDBC-драйвер в webapp /WEB-INF/lib, но только на сервере /lib. Если вы все еще сохраняете его в файле /WEB-INF/lib в webapp, вам необходимо зарегистрировать его вручную и отменить его с помощью ServletContextListener.
  2. Перейти на Tomcat 6.0.23 или старше, чтобы вы не беспокоились об этих предупреждениях , Но он будет тихо хранить утечку памяти. Не знаю, хорошо ли это знать. Подобные утечки памяти являются одной из основных причин, стоящих перед проблемами OutOfMemoryError во время горячих рассылок Tomcat.
  3. Переместите JDBC-драйвер в папку /lib Tomcat и подключите пул данных к источнику данных для управления драйвером. Обратите внимание, что встроенный DBCP от Tomcat не отменяет регистрацию драйверов должным образом при закрытии. См. Также ошибку DBCP-322 , которая закрыта как WONTFIX. Вы хотели бы заменить DBCP другим пулом соединений, который лучше выполняет свою работу, чем DBCP. Например, HikariCP , BoneCP или, возможно, Tomcat JDBC Pool .
273
ответ дан BalusC 18 August 2018 в 11:39
поделиться
  • 1
    Это хороший совет. Это не предупреждение утечки памяти, это предупреждение о том, что Tomcat предпринял некоторые принудительные действия для предотвращения утечки – matt b 23 July 2010 в 18:43
  • 2
    Если вариант (1) - это путь, почему Tomcat регистрирует их как SEVERE? SEVERE для меня означает «страница администратора», а не «игнорировать». – Peter Becker 18 October 2011 в 00:16
  • 3
  • 4
    @sproketboy: А? Вы назначали артефакты JDBC в качестве полей класса, который, в свою очередь, хранится в сеансе HTTP? – BalusC 28 June 2013 в 00:44
  • 5
    Я предполагаю, что это обычно причина 3 (наличие библиотеки в wAR, а не lib). – lapo 25 November 2014 в 10:42

В вашем контексте контекст-слушатель контекстного методаDestroyed () вручную отмените регистрацию драйверов:

        // This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                LOG.log(Level.INFO, String.format("deregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                LOG.log(Level.SEVERE, String.format("Error deregistering driver %s", driver), e);
            }

        }
154
ответ дан ae6rt 18 August 2018 в 11:39
поделиться
  • 1
    Оно работает! javabeat.net/servletcontextlistener-example может помочь реализовать прослушиватель контекста сервлета – Vadim Zin4uk 4 December 2013 в 14:44
  • 2
    Это потенциально опасно в общей среде, так как вам может не потребоваться отменить регистрацию доступных all JDBC-драйверов. См. мой ответ для более безопасного подхода. – megaflop 28 May 2014 в 14:01

Я столкнулся с этой проблемой, когда я развертывал приложение Grails на AWS. Это вопрос драйвера JDBC по умолчанию для драйвера org.h2. Как вы можете видеть это в Datasource.groovy внутри вашей папки конфигурации. Как вы можете видеть ниже:

dataSource {
    pooled = true
    jmxExport = true
    driverClassName = "org.h2.Driver"   // make this one comment
    username = "sa"
    password = ""
}

Прокомментируйте эти строки везде, где упоминается org.h2.Driver в файле datasource.groovy, если вы не используете эту базу данных. В противном случае вам нужно загрузить этот файл jar базы данных.

Спасибо.

0
ответ дан AJT_82 18 August 2018 в 11:39
поделиться

Решение для развертываний для каждого приложения

Это прослушиватель, который я написал для решения проблемы: он автоматически определяет, был ли водитель зарегистрирован и действует соответственно .it

Важно: это должен использоваться ТОЛЬКО, когда баннер драйвера развертывается в WEB-INF / lib, а не в Tomcat / lib, как многие из них предлагают, так что каждое приложение может позаботиться о своем собственном драйвере и запустить на нетронутом Tomcat. Таким образом, это должно быть IMHO.

Просто настройте слушателя в вашем web.xml перед любым другим и наслаждайтесь.

добавить в верхней части web.xml :

<listener>
    <listener-class>utils.db.OjdbcDriverRegistrationListener</listener-class>    
</listener>

сохранить как utils / db / OjdbcDriverRegistrationListener.java :

package utils.db;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import oracle.jdbc.OracleDriver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Registers and unregisters the Oracle JDBC driver.
 * 
 * Use only when the ojdbc jar is deployed inside the webapp (not as an
 * appserver lib)
 */
public class OjdbcDriverRegistrationListener implements ServletContextListener {

    private static final Logger LOG = LoggerFactory
            .getLogger(OjdbcDriverRegistrationListener.class);

    private Driver driver = null;

    /**
     * Registers the Oracle JDBC driver
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        this.driver = new OracleDriver(); // load and instantiate the class
        boolean skipRegistration = false;
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            if (driver instanceof OracleDriver) {
                OracleDriver alreadyRegistered = (OracleDriver) driver;
                if (alreadyRegistered.getClass() == this.driver.getClass()) {
                    // same class in the VM already registered itself
                    skipRegistration = true;
                    this.driver = alreadyRegistered;
                    break;
                }
            }
        }

        try {
            if (!skipRegistration) {
                DriverManager.registerDriver(driver);
            } else {
                LOG.debug("driver was registered automatically");
            }
            LOG.info(String.format("registered jdbc driver: %s v%d.%d", driver,
                    driver.getMajorVersion(), driver.getMinorVersion()));
        } catch (SQLException e) {
            LOG.error(
                    "Error registering oracle driver: " + 
                            "database connectivity might be unavailable!",
                    e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Deregisters JDBC driver
     * 
     * Prevents Tomcat 7 from complaining about memory leaks.
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        if (this.driver != null) {
            try {
                DriverManager.deregisterDriver(driver);
                LOG.info(String.format("deregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                LOG.warn(
                        String.format("Error deregistering driver %s", driver),
                        e);
            }
            this.driver = null;
        } else {
            LOG.warn("No driver to deregister");
        }

    }

}
8
ответ дан Andrea Ratto 18 August 2018 в 11:39
поделиться
  • 1
    Совет. С сервлета 3.0 вы можете аннотировать свой класс с помощью @WebListener и опустить конфигурацию web.xml. – Basil Bourque 12 May 2016 в 03:02
  • 2
    Правда, просто убедитесь, что он поднят с приоритетом достаточно высоким, так что никто не должен использовать драйвер до или после. – Andrea Ratto 24 August 2016 в 01:32

Я обнаружил, что реализация простого метода destroy () для деинсталляции любых драйверов JDBC прекрасно работает.

/**
 * Destroys the servlet cleanly by unloading JDBC drivers.
 * 
 * @see javax.servlet.GenericServlet#destroy()
 */
public void destroy() {
    String prefix = getClass().getSimpleName() +" destroy() ";
    ServletContext ctx = getServletContext();
    try {
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while(drivers.hasMoreElements()) {
            DriverManager.deregisterDriver(drivers.nextElement());
        }
    } catch(Exception e) {
        ctx.log(prefix + "Exception caught while deregistering JDBC drivers", e);
    }
    ctx.log(prefix + "complete");
}
6
ответ дан animuson 18 August 2018 в 11:39
поделиться
  • 1
    Это потенциально опасно в общей среде, так как вам может не потребоваться отменить регистрацию доступных all JDBC-драйверов. См. мой ответ для более безопасного подхода. Кроме того, это действительно должно выполняться в ServletContextListener, а не на каждом сервлете, так как ваш JDBC-драйвер является общим для всех ваших сервлетов в вашем webapp. – megaflop 28 May 2014 в 14:14

Я нашел ту же проблему с Tomcat версии 6.026.

Я использовал Mysql JDBC.jar в библиотеке WebAPP, а также в TOMCAT Lib.

Чтобы исправить это, удалив Jar из папки TOMCAT lib.

Итак, я понимаю, что TOMCAT правильно обрабатывает утечку памяти JDBC. Но если JSB JQB JQB дублируется в WebApp и Tomcat Lib, Tomcat сможет обрабатывать только банку в папке Tomcat Lib.

0
ответ дан Bharat 18 August 2018 в 11:39
поделиться
6
ответ дан Collin Peters 18 August 2018 в 11:39
поделиться

У меня была аналогичная проблема, но дополнительно я получал ошибку Java Heap Space в любое время, когда я модифицировал / сохранил JSP-страницы с сервером Tomcat, поэтому контекст не был полностью перезаряжен.

Мои версии были Apache Tomcat 6.0.29 и JDK 6u12.

Обновление JDK до 6u21, как предлагается в Ссылки в разделе URL http: / /wiki.apache.org/tomcat/MemoryLeakProtection решил проблему Java Heap Space (контекст теперь перезагружает OK), хотя ошибка драйвера JDBC все еще появляется.

2
ответ дан Francisco Alvarado 18 August 2018 в 11:39
поделиться

Удаляет приложение (tomcat6). Файлы conf сохраняются. Это как-то ломается. Я не уверен, как это делается.

-10
ответ дан Ivan Georgiev 18 August 2018 в 11:39
поделиться
  • 1
    Отвечает ли он на вопрос? Разве это не комментарий? – CCoder 13 November 2012 в 06:41
24
ответ дан kenor 18 August 2018 в 11:39
поделиться

Чтобы предотвратить утечку памяти, просто отмените регистрацию драйвера при отключении контекста.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mywebsite</groupId>
    <artifactId>emusicstore</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.9</source>
                    <target>1.9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- ... -->

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

MyWebAppContextListener.java

package com.emusicstore.utils;

import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

public class MyWebAppContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("************** Starting up! **************");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("************** Shutting down! **************");
        System.out.println("Destroying Context...");
        System.out.println("Calling MySQL AbandonedConnectionCleanupThread checkedShutdown");
        AbandonedConnectionCleanupThread.checkedShutdown();

        ClassLoader cl = Thread.currentThread().getContextClassLoader();

        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();

            if (driver.getClass().getClassLoader() == cl) {
                try {
                    System.out.println("Deregistering JDBC driver {}");
                    DriverManager.deregisterDriver(driver);

                } catch (SQLException ex) {
                    System.out.println("Error deregistering JDBC driver {}");
                    ex.printStackTrace();
                }
            } else {
                System.out.println("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
            }
        }
    }

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <listener>
        <listener-class>com.emusicstore.utils.MyWebAppContextListener</listener-class>
    </listener>

<!-- ... -->

</web-app>

Источник , который вдохновил меня на исправление этой ошибки.

0
ответ дан King-Wizard 18 August 2018 в 11:39
поделиться

Это чисто проблема регистрации / снятия регистрации с сервера в mysql`s driver или tomcats webapp-classloader. Скопируйте mysql-драйвер в папку tomcats lib (так что он загружен jvm напрямую, а не tomcat), и сообщение исчезнет. Это приводит к выгрузке драйвера mysql jdbc только при отключении JVM, и никто не заботится о утечке памяти.

14
ответ дан Lawrence Dol 18 August 2018 в 11:39
поделиться
  • 1
    что не работает ... Я попытался скопировать драйвер jdbc, если вы скажете: TOMCAT_HOME / lib / postgresql-9.0-801.jdbc4.jar - Tomcat 7.0 \ lib \ postgresql-9.0-801.jdbc4.jar без результатов ... – FAjir 17 June 2011 в 13:50
  • 2
    @Florito - вы должны удалить его из своих веб-приложений WEB-INF / lib, а также – Collin Peters 5 July 2011 в 17:20
72
ответ дан megaflop 18 August 2018 в 11:39
поделиться

Если вы получаете это сообщение от измененного военного изменения Maven, укажите область действия драйвера JDBC и поместите его копию в каталог lib. Например:

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.18</version>
  <!-- put a copy in /usr/share/tomcat7/lib -->
  <scope>provided</scope>
</dependency>
8
ответ дан TimP 18 August 2018 в 11:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: