获取java.lang.NoClassDefFoundError:无法初始化类oracle.jdbc.OracleDriver异常 [英] Getting java.lang.NoClassDefFoundError: Could not initialize class oracle.jdbc.OracleDriver exception

查看:714
本文介绍了获取java.lang.NoClassDefFoundError:无法初始化类oracle.jdbc.OracleDriver异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用JDBC驱动程序访问数据库时,我看到一些奇怪的行为.这是代码片段:

I am seeing some weird behavior when attempting to access a database using JDBC drivers. Here's the code fragment:

LOGGER.debug("driver is " + driver);
try {
    Class.forName(driver);
    LOGGER.debug("got driver");
} catch (Throwable t) {
    LOGGER.debug("throwable getting driver " + driver);
    t.printStackTrace(System.out);
    throw t;
}

运行此命令时,这就是我在堆栈跟踪中看到的内容.

When I run this, here's what I see in the stack trace.

08:20:00.417 [main] DEBUG - driver is com.sybase.jdbc4.jdbc.SybDriver
08:20:00.604 [main] DEBUG - throwable getting driver com.sybase.jdbc4.jdbc.SybDriver
java.lang.NoClassDefFoundError: Could not initialize class oracle.jdbc.OracleDriver
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:398)
        at java.sql/java.sql.DriverManager.isDriverAllowed(DriverManager.java:555)
        at java.sql/java.sql.DriverManager.isDriverAllowed(DriverManager.java:547)
        at java.sql/java.sql.DriverManager.getDrivers(DriverManager.java:449)
        at java.sql/java.sql.DriverManager.getDrivers(DriverManager.java:426)
        at com.sybase.jdbc4.jdbc.SybDriver.registerWithDriverManager(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybDriver.<init>(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybDriver.<clinit>(Unknown Source)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:315)
        ... my code

因此我可以看到我要获取的驱动程序名称是com.sybase.jdbc4.jdbc.SybDriver,这是正确的,但是由于某种原因,DriverManager正在寻找oracle.jdbc.OracleDriver.

So I can see that the driver name that I am trying to get is com.sybase.jdbc4.jdbc.SybDriver which is correct, but for some reason, the DriverManager is looking for oracle.jdbc.OracleDriver.

这是怎么回事?这段代码已经运行了好几年了,我能想到的唯一其他相关信息是我最近将这台机器上的JDK升级到了Open JDK 11.

What is going on? This code has been working well for years, and the only other relevant information I can think of is that I have recently upgraded the JDK on this machine to Open JDK 11.

>java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

推荐答案

这不是一个完整的答案,但似乎与自动驱动程序加载结合在一起是一个类加载问题.

This is not a complete answer, but it seems to be a class loading problem in combination with automatic driver loading.

当您显式使用Class.forName加载JDBC驱动程序时,该驱动程序应在java.sql.DriverManager中进行自身注册.

When you explicitly use Class.forName to load a JDBC driver, the driver should register itself with java.sql.DriverManager.

查看堆栈跟踪,具体是:

Looking at the stack trace, specifically:

    at java.sql/java.sql.DriverManager.getDrivers(DriverManager.java:426)
    at com.sybase.jdbc4.jdbc.SybDriver.registerWithDriverManager(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybDriver.<init>(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybDriver.<clinit>(Unknown Source)
    at java.base/java.lang.Class.forName0(Native Method)

Sybase驱动程序在自行注册(?)之前错误地检查了当前注册的驱动程序(使用DriverManager.getDrivers).更糟糕的是,它是由驱动程序构造函数而不是静态初始化程序完成的,这有可能导致驱动程序加载死锁.行为正确的驱动程序应从JDBC 4.3第9.2节中指定的静态初始化程序中调用DriverManager.registerDriver:

The Sybase driver incorrectly checks currently registered drivers (using DriverManager.getDrivers) before (?) registering itself. And even worse, it does this from the driver constructor instead of a static initializer, which could potentially lead to a driver loading deadlock. A proper behaving driver should call DriverManager.registerDriver from a static initializer as specified in JDBC 4.3 section 9.2:

JDBC驱动程序必须实现Driver接口,并且 实现必须包含一个将被调用的静态初始化器 加载驱动程序时.该初始化器注册一个新实例 DriverManager本身,如代码示例9-1所示.

JDBC drivers must implement the Driver interface, and the implementation must contain a static initializer that will be called when the driver is loaded. This initializer registers a new instance of itself with the DriverManager, as shown in CODE EXAMPLE 9-1.

public class AcmeJdbcDriver implements java.sql.Driver {
    static {
        java.sql.DriverManager.registerDriver(new AcmeJdbcDriver());
    }
    ... 
} 

代码示例9-1用于实现java.sql.Driver

CODE EXAMPLE 9-1 Example static initializer for a driver implementing java.sql.Driver

加载Driver实现时,静态初始值设定项将 自动注册驱动程序的实例.

When a Driver implementation is loaded, the static initializer will automatically register an instance of the driver.

由于调用了DriverManager.getDrivers,它将自动在META-INF/service/java.sql.Driver文件(以及系统属性jdbc.drivers中的文件)的类路径上加载驱动程序.

Because DriverManager.getDrivers is called, it will automatically load drivers on the classpath in META-INF/service/java.sql.Driver files (and those in the system property jdbc.drivers).

看来是发现了Oracle JDBC驱动程序,但是随后检查该驱动程序是否在isDriverAllowed的当前类加载器中可用,并显示NoClassDefFoundError失败(检查可以捕获异常,但不能捕获错误,也许应该).

It looks like the Oracle JDBC driver was discovered and loaded this way, but then a check if the driver is available in the current class loader in isDriverAllowed fails with a NoClassDefFoundError (the check catches exceptions, but not errors, and maybe it should).

作为一种解决方法,您应该从类路径中删除Oracle JDBC驱动程序,或者找出为什么它在当前类加载器中不可用.

As a workaround, you should either remove the Oracle JDBC driver from your class path, or find out why it is not available in the current class loader.

为进一步诊断,请尝试在代码中调用DriverManager.getDrivers()Class.forName("oracle.jdbc.Driver)或什至new oracle.jdbc.Driver(),然后查看会发生什么情况.

As further diagnosis, try to call DriverManager.getDrivers(), Class.forName("oracle.jdbc.Driver) or even new oracle.jdbc.Driver() in your code and see what happens.

您可能还想检查Sybase驱动程序的版本,如果有较新的版本不进行此检查,尽管这可能只会导致错误在代码的其他地方发生.

You may also want to check the version of your Sybase driver, and if there is a newer version that doesn't do this check, although that may simply cause the error to occur elsewhere in your code.

这篇关于获取java.lang.NoClassDefFoundError:无法初始化类oracle.jdbc.OracleDriver异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆