骆言 2022-11-25 21:18 采纳率: 91.7%
浏览 88
已结题

数据源 Druid 配置问题,内存泄漏

java tomcat maven war 项目

用 druid 连接 mysql 数据库

运行没毛病,就是报告内存泄漏

十一月 25, 2022 8:56:52 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads 警告: Web应用程序[todo-list]似乎启动了一个名为[Druid-ConnectionPool-Create-2023152835]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[ sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2813)]

日志全文

十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Server.服务器版本: Apache Tomcat/8.5.83
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 服务器构建:        Oct 3 2022 21:11:09 UTC
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 服务器版本号:      8.5.83.0
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 操作系统名称:      Windows 10
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: OS.版本:           10.0
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 架构:              amd64
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Java 环境变量:     C:\Program Files\Java\jdk1.8.0_301\jre
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Java虚拟机版本:    1.8.0_301-b09
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: JVM.供应商:        Oracle Corporation
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: CATALINA_BASE:     E:\temp1\tomcat-server-location
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: CATALINA_HOME:     F:\bin_java\apache-tomcat-8.5.83
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:52079
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -javaagent:C:\Users\lawsssscat\Desktop\sts-4.16.1.RELEASE\configuration\org.eclipse.osgi\268\0\.cp\lib\javaagent-shaded.jar
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dcatalina.base=E:\temp1\tomcat-server-location
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dcatalina.home=F:\bin_java\apache-tomcat-8.5.83
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dwtp.deploy=E:\temp1\tomcat-server-location\wtpwebapps
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Djava.endorsed.dirs=F:\bin_java\apache-tomcat-8.5.83\endorsed
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dfile.encoding=UTF-8
十一月 25, 2022 8:56:00 下午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent
信息: 在java.library.path:[C:\Program Files\Java\jdk1.8.0_301\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\Java\jdk1.8.0_301\jre\bin;C:/Users/lawsssscat/Desktop/sts-4.16.1.RELEASE//plugins/org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_17.0.4.v20221004-1257/jre/bin/server;C:/Users/lawsssscat/Desktop/sts-4.16.1.RELEASE//plugins/org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_17.0.4.v20221004-1257/jre/bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\Git\bin;C:\Program Files\nodejs\;C:\Program Files (x86)\Tencent\微信web开发者工具\dll;C:\Program Files\dotnet\;C:\Program Files\lua;C:\Program Files\luarocks;C:\MinGW\bin;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Program Files\MySQL\MySQL Utilities 1.6\;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\Ruby31-x64\bin;C:\Ruby24-x64\bin;C:\Users\lawsssscat\AppData\Local\Microsoft\WindowsApps;C:\Program Files\qemu;C:\Users\lawsssscat\AppData\Roaming\npm;C:\Users\lawsssscat\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files\ffmpeg\bin;E:\nodejs\node_global;C:\Users\lawsssscat\AppData\Local\GitHubDesktop\bin;C:\Users\lawsssscat\AppData\Local\Programs\Python\Python310;C:\Users\lawsssscat\Desktop\cmder;C:\cmake\bin;C:\bash_extend;F:\bin_java\apache-maven-3.8.6\bin;C:\Program Files\Java\jdk1.8.0_301\bin;F:\bin_db\mysql-8.0.31-winx64\bin;;C:\Users\lawsssscat\Desktop\sts-4.16.1.RELEASE;;.]上找不到基于APR的Apache Tomcat本机库,该库允许在生产环境中获得最佳性能
十一月 25, 2022 8:56:00 下午 org.apache.coyote.AbstractProtocol init
信息: 初始化协议处理器 ["http-nio-8080"]
十一月 25, 2022 8:56:00 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 418 ms
十一月 25, 2022 8:56:00 下午 org.apache.catalina.core.StandardService startInternal
信息: 正在启动服务[Catalina]
十一月 25, 2022 8:56:00 下午 org.apache.catalina.core.StandardEngine startInternal
信息: 正在启动 Servlet 引擎:[Apache Tomcat/8.5.83]
十一月 25, 2022 8:56:00 下午 org.apache.jasper.servlet.TldScanner scanJars
信息: 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
十一月 25, 2022 8:56:01 下午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
警告: 使用[SHA1PRNG]创建会话ID生成的SecureRandom实例花费了[172]毫秒。
十一月 25, 2022 8:56:01 下午 org.apache.jasper.servlet.TldScanner scanJars
信息: 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
十一月 25, 2022 8:56:01 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: 把web 应用程序部署到目录 [E:\temp1\tomcat-server-location\webapps\todo-list-pkg]
十一月 25, 2022 8:56:01 下午 org.apache.jasper.servlet.TldScanner scanJars
信息: 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
十一月 25, 2022 8:56:01 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Web应用程序目录[E:\temp1\tomcat-server-location\webapps\todo-list-pkg]的部署已在[316]毫秒内完成
十一月 25, 2022 8:56:01 下午 org.apache.coyote.AbstractProtocol start
信息: 开始协议处理句柄["http-nio-8080"]
十一月 25, 2022 8:56:01 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 1174 ms
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
十一月 25, 2022 8:56:06 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
十一月 25, 2022 8:56:52 下午 org.apache.catalina.core.StandardContext reload
信息: 已开始重新加载名为[/todo-list]的上下文
十一月 25, 2022 8:56:52 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesJdbc
警告: Web应用程序 [todo-list] 注册了JDBC驱动程序 [com.alibaba.druid.proxy.DruidDriver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
十一月 25, 2022 8:56:52 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesJdbc
警告: Web应用程序 [todo-list] 注册了JDBC驱动程序 [com.mysql.jdbc.Driver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
十一月 25, 2022 8:56:52 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: Web应用程序[todo-list]似乎启动了一个名为[Abandoned connection cleanup thread]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)]
十一月 25, 2022 8:56:52 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: Web应用程序[todo-list]似乎启动了一个名为[Druid-ConnectionPool-Create-2023152835]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
 com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2813)]
十一月 25, 2022 8:56:52 下午 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
警告: Web应用程序[todo-list]似乎启动了一个名为[Druid-ConnectionPool-Destroy-2023152835]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
 java.lang.Thread.sleep(Native Method)
 com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:2913)]
十一月 25, 2022 8:56:52 下午 org.apache.jasper.servlet.TldScanner scanJars
信息: 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
十一月 25, 2022 8:56:52 下午 org.apache.catalina.core.StandardContext reload
信息: 已完成重新加载名为[/todo-list]的上下文
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
十一月 25, 2022 9:05:20 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited

查看数据库连接,确实有问题:

  1. 每次连接数据库会创建10个连接(这应该正常,线程池)
  2. 长时间(大概10min)不与数据库交互,数据库连接并没有断开(这也没啥。问题是下面)
  3. 一段时间后,再次访问数据库,会创建新的10个连接。问题是,旧的10个连接并不会关闭!
  4. 程序长时间运行的结果是,创建了一堆与数据库的连接,而只有其中10个在工作。
  5. 直到程序关闭,数据库连接才断开

img

连接配置

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.1.7777:111111/xxxxx
username=bbbb
password=xxxxx
initialSize=10
maxActive=20
maxWait=10000

获取、销毁连接代码

package com.lawsssscat.web.util;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

/**
 * 
 * 1. 从数据源获取数据库连接
 * 2. 将数据源绑定到ThreadLocal
 * 3. 释放线程时和本地线程解除绑定
 * 
 * @author lawsssscat
 *
 */
public class JDBCUtils {

    // 数据源成员变量设置为静态资源,单例性
    private static DataSource dataSource;
    
    // 由于ThreadLocal对象需要作为绑定数据时的key从线程key-value对中获取数据,因此,要保证唯一性
    // 加static声明为静态资源既可保证唯一性
    final private static ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<>();
    
    // 在静态代码块中初始化数据源
    static {
        // 从 jdbc.properties 文件中读取数据库的信息
        // 基于WEB-INFO/classes(类路径根目录)获取配置文件,保证可移植性
        
        // 1. 获取当前的类加载器
        ClassLoader classLoader = JDBCUtils.class.getClassLoader();
        // 2. 通过类加载器对象从类路径根目录下读取文件
        InputStream stream = classLoader.getResourceAsStream("jdbc.properties");
        // 3. 使用Properties类封装属性文件中的数据
        Properties properties = new Properties();
        try {
            properties.load(stream);
            //4. 根据Properties对象(已封装了数据库连接信息)
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
            // 立即终止
            throw new RuntimeException(e);
        }
    }
    
    public static Connection getConnection() throws SQLException {
        Connection connection = connectionThreadLocal.get();
        if(connection==null) {
            connection = dataSource.getConnection();
            connectionThreadLocal.set(connection);
        }
        return connection;
    }
    
    public static void releaseConnection() throws SQLException {
        Connection connection = connectionThreadLocal.get();
        if(connection != null) {
            // 将当前数据库连接从当前线程上移除
            connectionThreadLocal.remove();
            // 放后面,因为可能抛出错误!
            connection.close();
        }
    }
}

filter 中获取连接

package com.lawsssscat.web.filter;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.lawsssscat.web.util.BooleanHelper;
import com.lawsssscat.web.util.JDBCUtils;
import com.lawsssscat.web.util.WebHelper;
import com.lawsssscat.web.util.WebVariable;

public class TransactionFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        // 静态资源跳过处理
        if(BooleanHelper.isTrue(WebHelper.getRequestVariable(WebVariable.REQUEST_STATIC_RESOURCE))) {
            chain.doFilter(request, response);
            return;
        }
        
        // 获取数据库连接
        // ⭐️ 重要:需要保证参与事务的多个数据库操作(SQL语句)使用的是同一个数据库连接
        Connection connection = null;
        try {
            connection = JDBCUtils.getConnection();
            
            // 取消自动提交
            connection.setAutoCommit(false);
            
            // 业务处理
            chain.doFilter(request, response);
            
            // 业务处理成功,提交事务
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                // 业务处理失败,回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                // TODO mark
                e1.printStackTrace();
            }
            
        } finally {
            try {
                JDBCUtils.releaseConnection();
            } catch (SQLException e) {
                // TODO mark
                e.printStackTrace();
            }
        }
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        
    }

}
  • 写回答

2条回答 默认 最新

  • 骆言 2022-11-28 19:53
    关注

    啥也没改,把druid退回到更多人用版本,好像就没有这种情况了:

    1.2.8 => 1.1.10

    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>  
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
    

    猜是1.2.8版本的超时关连接逻辑有问题

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 12月6日
  • 已采纳回答 11月28日
  • 修改了问题 11月25日
  • 修改了问题 11月25日
  • 展开全部

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?