// Use the system classloader as the victim for all this
// ClassLoader pinning we're about to do.
Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
/*
* First call to this loads all drivers in the current class
* loader
*/
if (driverManagerProtection) {
DriverManager.getDrivers();
}
2 回答
你能澄清一下“tomcat安装文件夹中的lib文件夹”是什么意思吗?它应该直接指向Tomcat根目录下的/ lib .
Tomcat 7 docs这样说:
正确的做法是使用DriverManager设置JNDI data source而不是在代码中创建一个_1574980 .
如果您使用的是JDK 7,我建议_j7c ._d从ojdbc6.jar推荐upgrading .
尝试在oracle的jdk 8_31上使用ojdbc7.jar和tomcat 8.0.20时遇到了同样的问题 .
我已将ojdbc7.jar放在$ CATALINA_BASE / lib中,如下所示:http://tomcat.apache.org/tomcat-8.0-doc/jndi-datasource-examples-howto.html然后预期java 's service provider mechanism to register the driver using tomcat' s "common" classloader,但它不起作用且驱动程序未注册 .
经过一些调试后,似乎tomcat的JreMemoryLeakPreventionListener从“system”类加载器而不是“common”类加载器(来自tomcat的代码)初始化DriverManager:
这里的问题是系统类加载器(在我的例子中是oracle的Launcher $ AppClassLoader)具有以下类路径:
由于ojbc7.jar不在此类路径中,因此DriverManager不会发现任何服务提供者,因此您的驱动程序只能显式注册,因为扫描只是在加载DriverManager类时从静态块完成(这是它的根本缺陷) ) .
我解决这个问题的第一个想法是将ojdbc jar添加到tomcat的$ CATALINA_BASE / bin / setenv.sh中的系统类加载器类路径中,如下所示:
这样,使用系统类加载器从JreMemoryLeakPreventionListener调用使用服务提供程序机制注册驱动程序 .
您必须非常小心,不要将ojdbc驱动程序放在webapp的类加载器中(例如,在您的WEB-INF / lib文件夹中包含ojdbc),因为这些类优先于父类加载器中的类 . 它有点复杂,但是当它使用调用者的类加载器调用Class.forName时,DriverManager本身可能会导致webapp的类加载器中的驱动程序的额外注册,因为它知道启动期间注册的类名 .