java.lang.NoClassDefFoundError错误的发生,是因为Java虚拟机在编译时能找到合适的类,而在运行时不能找到合适的类导致的错误。例如在运行时我们想调用某个类的方法或者访问这个类的静态成员的时候,发现这个类不可用,此时Java虚拟机就会抛出NoClassDefFoundError错误。与ClassNotFoundException的不同在于,这个错误发生只在运行时需要加载对应的类不成功,而不是编译时发生。(ClassNotFoundException的错误是因为在运行时类加载器在classpath下找不到需要加载的类)

最近在写一个从Excel导入到Oracle数据的小程序时遇到了这个问题。程序在初始化时尝试连接Oracle数据库,失败后手动连接,这时就会出现这个NoClassDefFoundError错误。检查发现是因为static块初始化报错,导致类没能初始化成功,再次调用这个类的方法时就会找不到这个类。每个static块只会在类被加载的时候执行且只会执行一次,因此如果想要重新尝试连接数据库的话必须重新启动程序,贴代码:

    static {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Properties prop = new  Properties();
            InputStream is = JdbcUtils.class.getClassLoader()
                    .getResourceAsStream("dbcpconfig.properties");
            prop.load(is);          
            MainDataSource = BasicDataSourceFactory.createDataSource(prop); 

            int num = ((BasicDataSource )MainDataSource).getInitialSize();
            int num2 = ((BasicDataSource )MainDataSource).getMaxTotal();

            System.out.println("初始化连接数 =  "+num);
            System.out.println("最大连接数 =  "+num2);
        } catch (Exception e) {
            System.out.println("Error in 初始化JdbcUtils—— " +e.getMessage());
            throw new ExceptionInInitializerError(e);
        }
    } 

如果连接超时,会在MainDataSource = BasicDataSourceFactory.createDataSource(prop)这里报错,抛出ExceptionInInitializerError的错误,这个时候这个类就没有初始化成功,我再尝试通过调用这个类里的方法进行数据库连接时就会报错。

处理方法是在static块里只加载数据库驱动,连接的语句通过函数来控制,这样就可以无限尝试连接Oracle数据库了。

//static块里加载Oracle驱动
static {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
//通过函数来尝试连接数据库
public static void tryConnect(){
        try {
            Properties prop = new  Properties();
            InputStream is = JdbcUtils.class.getClassLoader()
                    .getResourceAsStream("dbcpconfig.properties");
            prop.load(is);          
            MainDataSource = BasicDataSourceFactory.createDataSource(prop);

            int num = ((BasicDataSource )MainDataSource).getInitialSize();
            int num2 = ((BasicDataSource )MainDataSource).getMaxTotal();

            System.out.println("初始化连接数 =  "+num);
            System.out.println("最大连接数 =  "+num2);
        } catch (Exception e) {
            System.out.println("Error in 初始化JdbcUtils—— " +e.getMessage());
            throw new ExceptionInInitializerError(e);
        }
    }

参考文章:
怎么解决NoClassDefFoundError错误

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐