提问者:小点点

java. lang.NoClassDefFoundError:无法初始化类com.黑光.公共.DBManager


我正在尝试将我的服务文件连接到云sql实例。但我正在获取java. lang.NoClassDefFoundError:无法初始化类com.Blacklight.公共.DBManager

这是我的课

package com.blacklight.common;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

@WebListener("Initialize db upon initialization of application context")
public class DBManager implements ServletContextListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(DBManager.class);

    private static final Object dataSourceLock = new Object();
    private static DataSource dataSource = null;

    static {
        dataSource = initDataSource();
    }

    private static DataSource initDataSource() {
        synchronized (dataSourceLock) {
            try  {
                String username = "aaaa";
                String password = "bbbb";

                String driverName = "com.mysql.jdbc.Driver";
                String instance = "project-Id:location:database-name";


                if (dataSource == null) {

                    HikariConfig config = new HikariConfig();
                    config.setUsername(username);
                    config.setPassword(password);

                    config.setJdbcUrl("jdbc:mysql:///Features");
                    config.setUsername(username);
                    config.setPassword(password);

                    config.setDriverClassName(driverName);
                    config.setConnectionInitSql("SET NAMES 'utf8mb4'");
                    config.addDataSourceProperty("socketFactory","com.google.cloud.sql.mysql.SocketFactory");
                    config.addDataSourceProperty("cloudSqlInstance", instance);
                    config.addDataSourceProperty("characterEncoding", "UTF-8");
                    config.addDataSourceProperty("useUnicode", "true");
//                    config.addDataSourceProperty("noAccessToProcedureBodies", "true");

                    config.addDataSourceProperty("useSSL", "true");
                    config.addDataSourceProperty("ipTypes", "PRIVATE,PUBLIC");

                    config.setMaximumPoolSize(50);
                    config.setMinimumIdle(5);
                    config.setConnectionTimeout(10000);
                    config.setIdleTimeout(600000);
                    config.setMaxLifetime(1800000);

                    dataSource = new HikariDataSource(config);
                }
                return dataSource;
            } catch (Exception e) {
                System.out.println("Error");
                LOGGER.error(e.getMessage(), e);
            }
            throw new RuntimeException("Couldn't initialize datasource");
        }
    }

    public static Connection getConnection() throws SQLException {
        if (dataSource == null) {
            dataSource = initDataSource();
        }
        return dataSource.getConnection();
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        dataSource = initDataSource();
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        if (dataSource != null) {
            ((HikariDataSource) dataSource).close();
        }
    }

}

我的错误日志是com. blaklight.公共.DBManager initDataSource:初始化池失败:通信链路失败

成功发送到服务器的最后一个数据包是0毫秒前。驱动程序尚未收到来自服务器的任何数据包。com. zaxxer.hikari.pool.HikariPool$PoolFirst alizationException:初始化池失败:通信链路失败


共1个答案

匿名用户

这是在您的代码中存在一个类文件时引起的,该文件在编译时存在但在运行时找不到。寻找构建时和运行时类路径的差异。

这是一个简单的代码来说明您的错误实际上是什么:

NoClassDefFoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}

所以实际上它是以这种方式发生的:

这区分了java. lang.ClassNotFoundExceptionjava.lang.NoClassDefFoundError,其中ClassNotFoundException显示类在类路径上没有找到,这意味着我们正在尝试加载类定义;并且类在我们的类路径上不存在。

然而,在后者中,也就是您的情况,JVM在其内部类定义数据结构中查找类的定义,但没有找到它。

这意味着我们之前尝试从类路径加载一个类,但由于某种原因失败了-现在我们正在尝试再次使用该类(因此需要加载它,因为它上次失败了),但我们甚至不会尝试加载它,因为我们之前加载它失败了(并且有理由怀疑我们会再次失败)。

可能的解决方案:-

  1. 该类在JavaClasspath中不可用。
  2. 如果您在J2EE环境中工作,多个Classloader之间的Class可见性也会导致java. lang.NoClassDefFoundError,详细讨论请参见示例和场景部分。
  3. 检查日志文件中的java. lang.ExceptionInFirst alizerError。由于静态初始化失败而导致的NoClassDefFoundError很常见。
  4. 因为NoClassDefFoundError是java. lang.LinkageError的子类,所以如果其中一个依赖项(如本机库)可能不可用,它也可以出现。
  5. 任何启动脚本都会覆盖Classpath环境变量。
  6. 您可能正在使用jar命令运行程序,并且清单文件的ClassPath属性中未定义类。

资源

  • 解决NoClassDefFoundError的3种方法
  • 问题模式-NoClassDefFoundError