Aby zapobiec wyciekowi pamięci, sterownik JDBC został przymusowo niezarejestrowany

Otrzymuję ten Komunikat podczas uruchamiania mojej aplikacji internetowej. Działa dobrze, ale dostaję tę wiadomość podczas wyłączania.

SEVERE: aplikacja internetowa zarejestrowała sterownik JBDC [oracle.jdbc.kierowca.OracleDriver], ale nie udało się go wyrejestrować po zatrzymaniu aplikacji internetowej. Aby zapobiec wyciekowi pamięci, sterownik JDBC został przymusowo niezarejestrowany.

Każda pomoc mile widziana.

Author: BalusC, 2010-07-23

14 answers

Od wersji 6.0.24, Tomcat dostarcza wykrywanie wycieku pamięci funkcja, która z kolei może prowadzić do tego rodzaju komunikatów ostrzegawczych, gdy w aplikacji webapp /WEB-INF/lib jest sterownik kompatybilny z JDBC 4.0, który automatycznie-rejestruje się podczas uruchamiania aplikacji webapp za pomocą ServiceLoader API , ale które nie automatycznie - deregister się podczas zamykania webapp. Ta wiadomość jest czysto nieformalna, Tomcat podjął już działania zapobiegające wyciekowi pamięci odpowiednio.

Co możesz zrobić?

  1. Zignoruj te ostrzeżenia. Tomcat wykonuje swoją pracę dobrze. Rzeczywisty błąd jest w cudzym kodzie (o którym mowa w sterowniku JDBC), a nie w Twoim. Ciesz się, że Tomcat wykonał swoją pracę poprawnie i poczekaj, aż dostawca sterowników JDBC naprawi ją, abyś mógł uaktualnić sterownik. Z drugiej strony, nie powinieneś upuścić sterownika JDBC w aplikacji webapp /WEB-INF/lib, ale tylko w serwerze /lib. Jeśli nadal trzymasz go w aplikacji webapp /WEB-INF/lib, to należy ręcznie zarejestrować i wyrejestrować go za pomocą ServletContextListener.

  2. Zmień wersję na Tomcat 6.0.23 lub starszą, aby nie martwić się tymi ostrzeżeniami. Ale po cichu zachowa przeciekającą pamięć. Nie wiem, czy to dobrze wiedzieć. Tego rodzaju wycieki pamięci są jedną z głównych przyczyn OutOfMemoryError problemy podczas Tomcat hotdeployments.

  3. Przenieś sterownik JDBC do folderu Tomcat /lib i uzyskaj połączenie pooled datasource do zarządzania kierowca. Zauważ, że wbudowany Dbcp Tomcat nie wyrejestruje sterowników poprawnie po zamknięciu. Patrz również błąd DBCP-322 , który jest zamknięty jako WONTFIX. Wolisz zastąpić DBCP inną pulą połączeń, która wykonuje swoją pracę lepiej niż DBCP. Na przykład HikariCP, BoneCP, a może Tomcat JDBC Pool.

 274
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-16 19:21:35

W Twojej metodzie Servlet context listener contextDestroyed () ręcznie Wyrejestruj Sterowniki:

        // 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);
            }

        }
 156
Author: ae6rt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 17:20:48

Chociaż Tomcat nie przymusowo wyrejestrować sterownik JDBC dla Ciebie, niemniej jednak dobrą praktyką jest czyszczenie wszystkich zasobów utworzonych przez webapp na niszczenie kontekstu w przypadku przejścia do innego kontenera serwleta, który nie wykonuje kontroli wycieku pamięci, które Tomcat robi.

Jednak metodologia wyrejestrowania kierowców jest niebezpieczna. niektóre sterowniki zwracane przez metodę DriverManager.getDrivers() mogły zostać załadowane przez macierzysty ClassLoader (np. servlet classloader kontenera), a nie ClassLoader kontekstu aplikacji webapp (np. mogą znajdować się w folderze lib kontenera, a nie w webapp, a zatem są współdzielone przez cały kontener). Wyrejestrowanie ich wpłynie na inne webappy, które mogą ich używać (lub nawet sam kontener).

Dlatego przed wyrejestrowaniem należy sprawdzić, czy ClassLoader dla każdego sterownika jest Classloaderem aplikacji webapp. Tak więc, w metodzie contextlistener ' s contextDestroyed ():

public final void contextDestroyed(ServletContextEvent sce) {
    // ... 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);
        }
    }
}
 75
Author: megaflop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 12:56:55

Widzę, że ten problem często się pojawia. Tak, Tomcat 7 automatycznie wyrejestruje go, ale to naprawdę przejmuje kontrolę nad kodem i dobrą praktyką kodowania? Na pewno chcesz wiedzieć, że masz cały poprawny kod, aby zamknąć wszystkie obiekty, zamknąć wątki puli połączeń bazy danych i pozbyć się wszystkich ostrzeżeń. Oczywiście.

Tak to robię.

Krok 1: Zarejestruj słuchacza

www.xml

<listener>
    <listener-class>com.mysite.MySpecialListener</listener-class>
</listener>

Krok 2: Wdrożenie słuchacz

com.mysite.MySpecialListener.java

public class MySpecialListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // On Application Startup, please…

        // Usually I'll make a singleton in here, set up my pool, etc.
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // On Application Shutdown, please…

        // 1. Go fetch that DataSource
        Context initContext = new InitialContext();
        Context envContext  = (Context)initContext.lookup("java:/comp/env");
        DataSource datasource = (DataSource)envContext.lookup("jdbc/database");

        // 2. Deregister Driver
        try {
            java.sql.Driver mySqlDriver = DriverManager.getDriver("jdbc:mysql://localhost:3306/");
            DriverManager.deregisterDriver(mySqlDriver);
        } catch (SQLException ex) {
            logger.info("Could not deregister driver:".concat(ex.getMessage()));
        } 

        // 3. For added safety, remove the reference to dataSource for GC to enjoy.
        dataSource = null;
    }

}

Zapraszam do komentowania i / lub dodawania...

 24
Author: Spider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-30 10:46:09

Jest to problem czysto rejestracji sterowników / wyrejestrowania w sterowniku mysql lub tomcats webapp-classloader. Skopiuj sterownik mysql do folderu tomcats lib (więc jest ładowany bezpośrednio przez jvm, a nie przez tomcat), a wiadomość zniknie. To sprawia, że sterownik mysql jdbc może być rozładowany tylko przy wyłączaniu JVM, a nikt nie dba wtedy o wycieki pamięci.

 14
Author: sick old bastard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-31 02:43:55

Jeśli otrzymujesz tę wiadomość z Maven built war Zmień zakres sterownika JDBC na podany i umieść jego kopię w katalogu lib. Tak:

<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
Author: TimP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 10:15:11

Rozwiązanie dla wdrożeń per-app

To jest listener, który napisałem, aby rozwiązać problem: automatycznie wykrywa, czy sterownik się zarejestrował i działa accordingly.it

Ważne: jest on przeznaczony do użycia tylko wtedy, gdy driver Jar jest wdrożony w WEB-INF/lib, a nie w Tomcat /lib, jak wielu sugeruje, tak, że każda aplikacja może zadbać o swój własny sterownik i działać na nietkniętym Tomcacie. Tak powinno być IMHO.

Wystarczy skonfigurować słuchacza w swoim www.xml przed innymi i cieszyć.

Dodaj blisko góry www.xml :

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

Zapisz jako 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
Author: Andrea Ratto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-04 16:25:55

Dodam do tego coś, co znalazłem na wiosennych forach. Jeśli przeniesiesz JDBC driver JAR do folderu tomcat lib, zamiast wdrażać go za pomocą aplikacji webapp, Ostrzeżenie wydaje się znikać. Mogę potwierdzić, że to działało dla mnie

Http://forum.springsource.org/showthread.php?87335-Failure-to-unregister-the-MySQL-JDBC-Driver&p=334883#post334883

 6
Author: Collin Peters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-04 22:00:04

Odkryłem, że zaimplementowanie prostej metody destroy () do wyrejestrowania dowolnych sterowników JDBC działa dobrze.

/**
 * 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
Author: Darrin M. Gorski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-28 19:05:58

Miałem podobny problem, ale dodatkowo otrzymywałem błąd przestrzeni Java Heap za każdym razem, gdy modyfikowałem / zapisywałem strony JSP z uruchomionym serwerem Tomcat, dlatego kontekst nie był w pełni naładowany.

Moje wersje to Apache Tomcat 6.0.29 i JDK 6u12.

Aktualizacja JDK do 6u21, jak sugerowano w Linki sekcja URL http://wiki.apache.org/tomcat/MemoryLeakProtection rozwiązano problem przestrzeni sterty Java (kontekst ładuje się teraz normalnie) chociaż nadal pojawia się błąd sterownika JDBC.

 2
Author: Francisco Alvarado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-13 22:02:17

Znalazłem ten sam problem z Tomcat w wersji 6.026.

Użyłem Mysql JDBC.jar w Bibliotece WebAPP oraz w TOMCAT Lib.

Aby naprawić powyższe, usuwając Jar z folderu Tomcat lib.

Rozumiem, że TOMCAT prawidłowo radzi sobie z wyciekiem pamięci JDBC. Ale jeśli jar MYSQL JDBC jest duplikowany w WebApp i Tomcat Lib, Tomcat będzie w stanie obsłużyć tylko jar obecny w folderze Tomcat Lib.

 0
Author: Bharat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-24 16:03:09

Miałem do czynienia z tym problemem, gdy wdrażałem moją aplikację Grails na AWS. Jest to kwestia domyślnego sterownika JDBC org.H2 kierowca . Jak widać w Datasource.groovy wewnątrz folderu konfiguracji . Jak widać poniżej:

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

Skomentuj te linijki wszędzie tam, gdzie jest mowa org.h2.Driver w datasource.plik groovy, jeśli nie korzystasz z tej bazy danych . W przeciwnym razie musisz pobrać plik jar bazy danych .

Dzięki .

 0
Author: PyDevSRS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-08 17:21:17

Aby zapobiec wyciekowi pamięci, po prostu Wyrejestruj sterownik przy wyłączaniu kontekstu.

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");
            }
        }
    }

}

Www.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>

Źródło które zainspirowało mnie do tej poprawki.

 0
Author: King-Wizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-01 17:34:49

Usunięcie aplikacji (tomcat6) rozwiązuje problem. Pliki conf są zachowane. Jakoś się psuje. Nie jestem pewien, jak to robi.

 -10
Author: Ivan Georgiev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-31 16:33:58