当前位置: 首页 > 面试题库 >

为什么会收到JDBC驱动程序警告和ThreadLocal错误?

郎俊雅
2023-03-14
问题内容

我在GlassFish上运行我的应用程序,我使用Spring
Security和Hibernate。当我运行该应用程序时,以下警告和错误将显示在GlassFish控制台上。如何避免它们?

WARNING:   The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
SEVERE:   The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@1087985b]) and a value of type [org.hibernate.internal.SessionImpl] (value [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
SEVERE:   The web application [] created a ThreadLocal with key of type [net.sf.json.AbstractJSON$1] (value [net.sf.json.AbstractJSON$1@362386d7]) and a value of type [java.util.HashSet] (value [[]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
SEVERE:   The web application [] created a ThreadLocal with key of type [net.sf.json.AbstractJSON$1] (value [net.sf.json.AbstractJSON$1@362386d7]) and a value of type [java.util.HashSet] (value [[]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

hibernate.cfg.xml

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <property name="connection.url">
            jdbc:mysql://localhost:3306/myproject
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">12</property>

        <!-- SQL dialect -->
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>



        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

<!--         Disable the second-level cache -->

<!-- <property name="cache.provider_class">
            org.hibernate.cache.EhCacheProvider
        </property>

        <property name="hibernate.cache.use_query_cache">true</property>-->


        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

HibernateUtil.java

public class HibernateUtil {

   private static ServiceRegistry serviceRegistry;
   private static final ThreadLocal<Session> threadLocal = new ThreadLocal();
   private static SessionFactory sessionFactory;

   private static SessionFactory configureSessionFactory() {
        try {
            Configuration configuration = new Configuration();
            configuration.configure();
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();

            sessionFactory = configuration.buildSessionFactory(serviceRegistry);

            return sessionFactory;
        } catch (HibernateException e) {
            System.out.append("** Exception in SessionFactory **");
            e.printStackTrace();
        }
       return sessionFactory;
  }

  static {
    try {
      sessionFactory = configureSessionFactory();
    } catch (Exception e) {
      System.err.println("%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
    }
  }

  private HibernateUtil() {
  }

  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  public static Session getSession() throws HibernateException {
    Session session = threadLocal.get();

    if (session == null || !session.isOpen()) {
      if (sessionFactory == null) {
        rebuildSessionFactory();
      }
      session = (sessionFactory != null) ? sessionFactory.openSession() : null;
      threadLocal.set(session);
    }

    return session;
  }

  public static void rebuildSessionFactory() {
    try {
      sessionFactory = configureSessionFactory();
    } catch (Exception e) {
      System.err.println("%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
    }
  }

  public static void closeSession() throws HibernateException {
    Session session = (Session) threadLocal.get();
    threadLocal.set(null);

    if (session != null) {
      session.close();
    }
  }
}

问题答案:

这些是在服务器保持运行状态下重新部署应用程序时可能发生的错误消息。

如果是关闭场景或开发重新部署,则可以安全地忽略这些消息,仅当您需要在生产中重新部署时,这些消息才变得很重要,这种情况很少见。即使在生产中,大多数时候我们也想停止服务器进程并完全重启它。这是每个消息的一些详细信息,其含义是:

消息1-应用程序停止时未注销驱动程序:

警告:Web应用程序[]注册了JDBC驱动程序[com.mysql.jdbc.Driver],但在Web应用程序停止时未能注销它。为了防止内存泄漏,已强制注销JDBC驱动程序。

JDBC驱动程序在启动时以JVM级别单例注册,这是由服务器通过在服务器级别的文件夹中发布驱动程序jar来完成的。

在这种情况下,应用程序似乎带有驱动程序本身,而不是驱动程序被部署的方式。

要解决此问题,请从应用程序中删除驱动程序,然后在服务器级别上注册它。如果多个应用程序具有相同的驱动程序,这也会导致内存泄漏-

消息2-未清除ThreadLocal:

严重:Web应用程序[]创建了一个ThreadLocal,其键类型为[java.lang.ThreadLocal](值[java.lang.ThreadLocal@1087985b]),并且值类型为[org.hibernate.internal.SessionImpl],但未能成功在Web应用程序停止时将其删除。线程将随着时间的流逝而更新,以尝试避免可能的内存泄漏。

这意味着一个应用程序Spring线程在该线程中存储了一个Hibernate会话(每个线程作为数据存储区,可以通过ThreadLocal附加事物)。

但是,在重新启动应用程序时,线程没有清理会话,因此在重新使用线程后,重新部署后,该线程中存储的该变量可以看到。

这可能令人惊讶,但最糟糕的是,该会话指向其他对象,这些对象本身指向类,而这些对象指向重新部署之前的旧类加载器。

这意味着由于泄漏到先前部署的对象的“链接”,将不会大量收集对象树。结果是ClassLoader内存泄漏。

该消息指出,这种情况可能是由于未清理的ThreadLocals而发生的,并且将采取一些预防措施(开始杀死线程并创建新线程,而不是创建池,以消除泄漏的线程局部变量)。

总之,如果您不需要在生产中进行重新部署并始终重新启动服务器,则可以安全地忽略这些消息。



 类似资料:
  • 当我调试我的Mule应用程序时,我有错误: 我的java代码: 我的aaplicationContext: 我的app_name.properties: 我的pom: 我的类路径: 运行应用程序后的日志信息: 我还把h2-1.4.200.jar(当我从Anypoint Studio启动我的应用程序)到: 当我从mule服务器h2-1.4.200运行应用程序时。jar,我放在这里: 为什么找不到应用

  • Spring HATEOAS定义并注册包含序列化器的Jackson模块的,以将其和类型转换为HAL JSON表示。这些模块使用Jackson混合将序列化器绑定到如下类型: 这个mixin导致扩展

  • 查询从something_data中选择username作为col6、性别作为col1、last_name作为col2、email作为col3、first_name作为col4、something_uuid作为col5、group_email作为col7、deleted作为col8、puars作为col9,其中username=?;在/xx.yy.91.205:9042上未准备,请在重试执行之前准

  • 我不明白为什么我收到以下代码的警告: 未选中对<code>isAssignableFrom(类)的调用 当我使用< code>isInstance方法时(根据我的理解,它提供相同的结果),我没有得到警告:

  • 问题内容: 我正在学习Java和OOPS,并在日食中编写基本的Hello World时,我看到一个黄色三角形,告诉我 “实用程序类不应具有公共或默认构造函数” 。我不明白为什么会这样,这是什么意思?我在做什么不对? EDIT1:编辑代码以包括建议的更改。 仍然在类HelloWorld上收到警报。 编辑2: 创建了一个新类,现在可以使用了。谢谢乔恩,为什么旧​​班级还会发出警告?波希米亚语我仍然不知

  • 问题内容: 我正在尝试运行Junit测试,仅在没有maven的项目之前进行了配置,现在我正在尝试进行此集成,但是我停在了以下错误中: 这是我的pom: 这是我的带有spring3,jpa,hibernate4的applicationContext.xml: 这是我的测试: 问题答案: 您可以在项目中进行简单的测试,以确保类“ org.postgresql.Driver”在您的类路径中