From a8cd5bdd379b0797a009287575f72d6d70b5c03c Mon Sep 17 00:00:00 2001 From: markt Date: Sun, 29 Nov 2009 14:25:04 +0000 Subject: [PATCH] Add logging when a context fails to unregister a JDBC driver. Don't unregister the jdbc-obdc bridge driver that is loaded by the system classloader. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@885231 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/catalina/loader/JdbcLeakPrevention.java | 20 ++++++++++++++++++-- .../apache/catalina/loader/LocalStrings.properties | 1 + .../apache/catalina/loader/WebappClassLoader.java | 8 +++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/java/org/apache/catalina/loader/JdbcLeakPrevention.java b/java/org/apache/catalina/loader/JdbcLeakPrevention.java index 1fd7ea262..1aa103406 100644 --- a/java/org/apache/catalina/loader/JdbcLeakPrevention.java +++ b/java/org/apache/catalina/loader/JdbcLeakPrevention.java @@ -21,7 +21,9 @@ package org.apache.catalina.loader; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Enumeration; +import java.util.List; /** * This class is loaded by the {@link WebappClassLoader} to enable it to @@ -36,14 +38,28 @@ import java.util.Enumeration; */ public class JdbcLeakPrevention { - public void clearJdbcDriverRegistrations() throws SQLException { + /* + * This driver is visible to all classloaders but is loaded by the system + * class loader so there is no need to unload it. + */ + private static final String JDBC_ODBC_BRIDGE_DRIVER = + "sun.jdbc.odbc.JdbcOdbcDriver"; + + public List clearJdbcDriverRegistrations() throws SQLException { + List driverNames = new ArrayList(); + // Unregister any JDBC drivers loaded by the class loader that loaded // this class - ie the webapp class loader Enumeration drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); + if (JDBC_ODBC_BRIDGE_DRIVER.equals( + driver.getClass().getCanonicalName())) { + continue; + } + driverNames.add(driver.getClass().getCanonicalName()); DriverManager.deregisterDriver(driver); } - + return driverNames; } } diff --git a/java/org/apache/catalina/loader/LocalStrings.properties b/java/org/apache/catalina/loader/LocalStrings.properties index 37ed5042c..297af3118 100644 --- a/java/org/apache/catalina/loader/LocalStrings.properties +++ b/java/org/apache/catalina/loader/LocalStrings.properties @@ -33,6 +33,7 @@ webappClassLoader.jdbcRemoveFailed=JDBC driver de-registration failed webappClassLoader.jdbcRemoveStreamError=Exception closing input stream during JDBC driver de-registration webappClassLoader.stopped=Illegal access: this web application instance has been stopped already. Could not load {0}. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact. webappClassLoader.readError=Resource read error: Could not load {0}. +webappClassLoader.uncleareredReferenceJbdc=A web application registered the JBDC driver [{0}] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. webappClassLoader.wrongVersion=(unable to load class {0}) webappLoader.addRepository=Adding repository {0} webappLoader.deploy=Deploying class repositories to work directory {0} diff --git a/java/org/apache/catalina/loader/WebappClassLoader.java b/java/org/apache/catalina/loader/WebappClassLoader.java index cd82d6f44..74ad4d0aa 100644 --- a/java/org/apache/catalina/loader/WebappClassLoader.java +++ b/java/org/apache/catalina/loader/WebappClassLoader.java @@ -42,6 +42,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Vector; import java.util.jar.Attributes; @@ -1672,8 +1673,13 @@ public class WebappClassLoader defineClass("org.apache.catalina.loader.JdbcLeakPrevention", classBytes, 0, offset); Object obj = lpClass.newInstance(); - obj.getClass().getMethod( + @SuppressWarnings("unchecked") + List driverNames = (List) obj.getClass().getMethod( "clearJdbcDriverRegistrations").invoke(obj); + for (String name : driverNames) { + log.error(sm.getString( + "webappClassLoader.uncleareredReferenceJbdc", name)); + } } catch (Exception e) { // So many things to go wrong above... log.warn(sm.getString("webappClassLoader.jdbcRemoveFailed"), e); -- 2.11.0