大漠驼铃

置身浩瀚的沙漠,方向最为重要,希望此blog能向大漠驼铃一样,给我方向和指引。
Java,Php,Shell,Python,服务器运维,大数据,SEO, 网站开发、运维,云服务技术支持,IM服务供应商, FreeSwitch搭建,技术支持等. 技术讨论QQ群:428622099
随笔 - 238, 文章 - 3, 评论 - 117, 引用 - 0
数据加载中……

To prevent a memory leak, the JDBC Driver has been forcibly unregistered--有关Tomcat自动宕机的解决方案

最近有几个服务的Tomcat总是无缘无故的宕机,到了不得不解决的地步。
在Stackoverflow上找到比较有用的一篇文章,解决方案如下:
http://stackoverflow.com/questions/3320400/to-prevent-a-memory-leak-the-jdbc-driver-has-been-forcibly-unregistered
有以下几个解决途径:
  1. Ignore those warnings. Tomcat is doing its job right. The actual bug is in someone else's code (the JDBC driver in question), not in yours. Be happy that Tomcat did its job properly and wait until the JDBC driver vendor get it fixed so that you can upgrade the driver. On the other hand, you aren't supposed to drop a JDBC driver in webapp's /WEB-INF/lib, but only in server's /lib. If you still keep it in webapp's /WEB-INF/lib, then you should manually register and deregister it using a ServletContextListener.
    忽略警告。把WEB-INF/lib下的mysql驱动文件拷贝到Tomcat/lib下。如果仍然要放在WEB-INF/lib下,需要使用监听器手动的注册和注销。
    下面的文章介绍如何写监听器,http://javabeat.net/servletcontextlistener-example/, 当然如果是Servlet3.0, 使用注解方式设置监听也是可以的。
    下面的代码是如何注销。

    Step 1: Register a Listener
    web.xml
    <listener>
        
    <listener-class>com.mysite.MySpecialListener</listener-class>
    </listener>
    Step 
    2: Implement the Listener

    com.mysite.MySpecialListener.java

    public class MySpecialListener extends ApplicationContextListener {

        @Override
        
    public void contextInitialized(ServletContextEvent sce) {
            
    // On Application Startup, please…

            
    // Usually I'll make a singleton in here, set up my pool, etc.
        }

        @Override
        
    public void contextDestroyed(ServletContextEvent sce) {
          
    // This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
            Enumeration<Driver> drivers = DriverManager.getDrivers();
            while (drivers.hasMoreElements()) {
                Driver driver = drivers.nextElement();
                try {
                    DriverManager.deregisterDriver(driver);
                    LOG.log(Level.INFO, String.format("deregistering jdbc driver: %s", driver));
                } catch (SQLException e) {
                    LOG.log(Level.SEVERE, String.format("Error deregistering driver %s", driver), e);
                }

            }
        }

    }
  2. Downgrade to Tomcat 6.0.23 or older so that you will not be bothered with those warnings. But it will silently keep leaking memory. Not sure if that's good to know after all. Those kind of memory leaks are one of the major causes behind OutOfMemoryError issues during Tomcat hotdeployments.
    把Tomcat降级到低版本(6.0.23以下),虽然不会报错,但是还是存在内存益出的问题,这并不是一个好的解决方案。

  3. Move the JDBC driver to Tomcat's /lib folder and have a connection pooled datasource to manage the driver. Note that Tomcat's builtin DBCP does not deregister drivers properly on close. See also bug DBCP-322 which is closed as WONTFIX. You would rather like to replace DBCP by another connection pool which is doing its job better then DBCP. For exampleHikariCPBoneCP, or perhaps Tomcat JDBC Pool.
    把驱动文件移到Tomcat/lib文件夹下,不用使用DBCP,使用以下的连接池库,HikariCP, BoneCP,或者Tomcat JDBC Pool.

  4. MAVEN项目

    If you are getting this message from a Maven built war change the scope of the JDBC driver to provided, and put a copy of it in the lib directory. Like this:<dependency>,
    对于MAVEN项目,由于Tomcat中存在mysql驱动文件(1中介绍),这样在部署时就不会把mysql带到打包文件里,注意是<scope>provided</scope>。

      <groupId>mysql</groupId>
      
    <artifactId>mysql-connector-java</artifactId>
      
    <version>5.1.18</version>
      
    <!-- put a copy in /usr/share/tomcat7/lib -->
      
    <scope>provided</scope>
    </dependency>
好了,如果您遇到同样的问题,可以和我沟通,联系方式见头部。

posted on 2016-08-03 10:59 草原上的骆驼 阅读(12494) 评论(0)  编辑  收藏 所属分类: JAVA基础知识JAVA框架


只有注册用户登录后才能发表评论。


网站导航: