Ich erhalte diese Meldung, wenn ich meine Webanwendung ausführe. Es läuft gut, aber ich bekomme diese Meldung beim Herunterfahren.
SCHWER: Eine Webanwendung hat den JBDC-Treiber [oracle.jdbc.driver.OracleDriver] registriert, die Registrierung konnte jedoch nicht aufgehoben werden, als die Webanwendung gestoppt wurde. Um einen Speicherverlust zu verhindern, wurde der JDBC-Treiber zwangsweise abgemeldet.
Jede Hilfe geschätzt.
Antworten:
Seit Version 6.0.24 wird Tomcat mit einer Speicherleckerkennungsfunktion ausgeliefert , die wiederum zu solchen Warnmeldungen führen kann, wenn sich in den Webanwendungen ein JDBC 4.0-kompatibler Treiber befindet,
/WEB-INF/lib
der sich beim Start der Webanwendung mithilfe der API automatisch registriert , der jedoch hat sich beim Herunterfahren der Webapp nicht automatisch abgemeldet . Diese Nachricht ist rein informell. Tomcat hat die Maßnahme zur Verhinderung von Speicherlecks bereits entsprechend ergriffen.ServiceLoader
Was kannst du tun?
Ignorieren Sie diese Warnungen. Tomcat macht seinen Job richtig. Der eigentliche Fehler liegt im Code einer anderen Person (dem fraglichen JDBC-Treiber) und nicht in Ihrem. Seien Sie froh, dass Tomcat seine Arbeit ordnungsgemäß ausgeführt hat, und warten Sie, bis der Hersteller des JDBC-Treibers das Problem behoben hat, damit Sie den Treiber aktualisieren können. Auf der anderen Seite sollten Sie keinen JDBC-Treiber in Webanwendungen ablegen
/WEB-INF/lib
, sondern nur in Servern/lib
. Wenn Sie es weiterhin in der Webanwendung behalten/WEB-INF/lib
, sollten Sie es manuell registrieren und mit einem abmeldenServletContextListener
.Downgrade auf Tomcat 6.0.23 oder älter, damit Sie nicht mit diesen Warnungen belästigt werden. Aber es wird stillschweigend Speicher verlieren. Ich bin mir nicht sicher, ob das gut zu wissen ist. Diese Art von Speicherlecks sind eine der Hauptursachen für
OutOfMemoryError
Probleme bei Tomcat-Hotdeployments.Verschieben Sie den JDBC-Treiber in den Tomcat-
/lib
Ordner und verfügen Sie über eine Datenquelle mit Verbindungspool, um den Treiber zu verwalten. Beachten Sie, dass das in Tomcat integrierte DBCP die Treiber beim Schließen nicht ordnungsgemäß abmeldet. Siehe auch Fehler DBCP-322, der als WONTFIX geschlossen ist. Sie möchten DBCP lieber durch einen anderen Verbindungspool ersetzen, der seine Aufgabe besser erfüllt als DBCP. Zum Beispiel HikariCP , BoneCP oder vielleicht Tomcat JDBC Pool .quelle
lib
).Melden Sie die Treiber in der KontextDestroyed () -Methode Ihres Servlet-Kontext-Listeners manuell ab:
quelle
Obwohl Tomcat den JDBC-Treiber für Sie zwangsweise abmeldet, empfiehlt es sich dennoch, alle von Ihrer Webanwendung bei Kontextzerstörung erstellten Ressourcen zu bereinigen, falls Sie in einen anderen Servlet-Container wechseln, der die von Tomcat durchgeführten Überprüfungen zur Verhinderung von Speicherlecks nicht durchführt.
Die Methode der pauschalen Abmeldung von Treibern ist jedoch gefährlich. Einige von der
DriverManager.getDrivers()
Methode zurückgegebene Treiber wurden möglicherweise vom übergeordneten ClassLoader (dh dem Classloader des Servlet-Containers) und nicht vom ClassLoader des Webapp-Kontexts geladen (z. B. befinden sie sich möglicherweise im lib-Ordner des Containers, nicht im Webapp-Ordner, und werden daher für den gesamten Container freigegeben ). Die Abmeldung dieser wirkt sich auf alle anderen Webanwendungen aus, die sie möglicherweise verwenden (oder sogar auf den Container selbst).Daher sollte überprüft werden, ob der ClassLoader für jeden Treiber der ClassLoader der Webanwendung ist, bevor die Registrierung aufgehoben wird. In der contextDestroyed () -Methode Ihres ContextListener:
quelle
if (cl.equals(driver.getClass().getClassLoader())) {
?DriverManager
. Ich habe einen ausführlicheren Kommentar unter github.com/spring-projects/spring-boot/issues/…Ich sehe, dass dieses Problem häufig auftritt. Ja, Tomcat 7 hebt die Registrierung automatisch auf, aber übernimmt es WIRKLICH die Kontrolle über Ihren Code und eine gute Codierungspraxis? Sicherlich möchten SIE wissen, dass Sie über den richtigen Code verfügen, um alle Ihre Objekte zu schließen, Threads des Datenbankverbindungspools herunterzufahren und alle Warnungen zu entfernen. Das tue ich auf jeden Fall.
So mache ich es.
Schritt 1: Registrieren Sie einen Listener
web.xml
Schritt 2: Implementieren Sie den Listener
com.mysite.MySpecialListener.java
Bitte zögern Sie nicht zu kommentieren und / oder hinzuzufügen ...
quelle
DataSource
aber KEINEclose
MethodecontextDestroyed
? Warum tun Sie Schritt 1 vor dem Schritt tun 2., woinitContext
,envContext
unddatasource
sind überhaupt nicht referenziert? Ichlookup
scheint nur einige Objekte zu bekommen, die Sie nicht brauchen. Schritt 3. ist völlig nutzlos. Es fügt sicherlich keine Sicherheit hinzu und sieht so aus, als würden Anfänger etwas tun, die nicht verstehen, wie GC funktioniert. Ich würde einfach mit stackoverflow.com/a/5315467/897024 gehen und alle Treiber entfernen.Dies ist ein reines Problem bei der Registrierung / Abmeldung von Treibern in mysqls Treiber oder Tomcats Webapp-Classloader. Kopieren Sie den MySQL-Treiber in den Ordner "tomcats lib" (also wird er direkt von jvm geladen, nicht von tomcat), und die Nachricht wird gelöscht. Dadurch wird der MySQL-JDBC-Treiber nur beim Herunterfahren der JVM entladen, und dann kümmert sich niemand um Speicherverluste.
quelle
Wenn Sie diese Nachricht von einem von Maven erstellten Krieg erhalten, ändern Sie den Bereich des JDBC-Treibers in "Bereitgestellt" und legen Sie eine Kopie davon im lib-Verzeichnis ab. So was:
quelle
Lösung für Bereitstellungen pro App
Dies ist ein Listener, den ich geschrieben habe, um das Problem zu lösen: Er erkennt automatisch, ob sich der Treiber registriert hat, und handelt entsprechend
Wichtig: Es darf NUR verwendet werden, wenn die Treiber-JAR in WEB-INF / lib bereitgestellt wird , nicht in Tomcat / lib, wie viele vermuten, damit jede Anwendung ihren eigenen Treiber pflegen und auf einem unberührten Tomcat ausführen kann . So sollte es IMHO sein.
Konfigurieren Sie einfach den Listener in Ihrer web.xml vor allen anderen und genießen Sie.
füge oben in der Datei web.xml hinzu :
Speichern unter utils / db / OjdbcDriverRegistrationListener.java :
quelle
@WebListener
und dieweb.xml
Konfiguration weglassen .Ich werde etwas hinzufügen, das ich in den Frühlingsforen gefunden habe. Wenn Sie Ihr JDBC-Treiber-JAR in den Ordner tomcat lib verschieben, anstatt es mit Ihrer Webanwendung bereitzustellen, scheint die Warnung zu verschwinden. Ich kann bestätigen, dass dies bei mir funktioniert hat
http://forum.springsource.org/showthread.php?87335-Failure-to-unregister-the-MySQL-JDBC-Driver&p=334883#post334883
quelle
Ich fand, dass die Implementierung einer einfachen destroy () -Methode zum Abmelden von JDBC-Treibern gut funktioniert.
quelle
Um diesen Speicherverlust zu verhindern, melden Sie den Treiber beim Herunterfahren des Kontexts einfach ab.
pom.xml
MyWebAppContextListener.java
web.xml
Quelle , die mich zu dieser Fehlerbehebung inspiriert hat.
quelle
Ich hatte ein ähnliches Problem, aber zusätzlich wurde jedes Mal ein Java Heap Space-Fehler angezeigt, wenn ich JSP-Seiten bei laufendem Tomcat-Server geändert / gespeichert habe. Daher wurde der Kontext nicht vollständig aufgeladen.
Meine Versionen waren Apache Tomcat 6.0.29 und JDK 6u12.
Durch das Aktualisieren von JDK auf 6u21, wie im Abschnitt " Referenzen " der URL http://wiki.apache.org/tomcat/MemoryLeakProtection vorgeschlagen, wurde das Problem mit dem Java- Heapspeicher behoben (der Kontext wird jetzt erneut geladen, OK), obwohl der JDBC-Treiberfehler weiterhin angezeigt wird.
quelle
Ich habe das gleiche Problem mit Tomcat Version 6.026 gefunden.
Ich habe die MySQL-Datei JDBC.jar sowohl in der WebAPP-Bibliothek als auch in TOMCAT Lib verwendet.
Um dies zu beheben, entfernen Sie das Jar aus dem Ordner TOMCAT lib.
Ich verstehe also, dass TOMCAT den JDBC-Speicherverlust ordnungsgemäß behandelt. Wenn die MYSQL-Jdbc-JAR-Datei jedoch in WebApp und Tomcat Lib dupliziert wird, kann Tomcat nur die im Tomcat Lib-Ordner vorhandene JAR-Datei verarbeiten.
quelle
Ich habe dieses Problem festgestellt, als ich meine Grails-Anwendung auf AWS bereitgestellt habe. Dies ist eine Frage des JDBC-Standardtreibers org.h2 . Wie Sie in der Datei Datasource.groovy in Ihrem Konfigurationsordner sehen können. Wie Sie unten sehen können:
Kommentieren Sie diese Zeilen überall dort, wo org.h2.Driver in der Datei datasource.groovy erwähnt wird, wenn Sie diese Datenbank nicht verwenden. Andernfalls müssen Sie diese Datenbank-JAR-Datei herunterladen.
Vielen Dank .
quelle
Dieser Fehler ist mir in einer Grails-Anwendung mit dem JTDS-Treiber 1.3.0 (SQL Server) passiert. Das Problem war eine falsche Anmeldung in SQL Server. Nachdem dieses Problem behoben wurde (in SQL Server), wurde meine App in Tomcat korrekt bereitgestellt. Tipp: Ich habe den Fehler in stacktrace.log gesehen
quelle