You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postgres JDBC的LazyCleaner是否会导致类加载器内存泄漏?

PostgreSQL JDBC驱动引发Tomcat类加载器内存泄漏的排查方案

问题本质

你将postgresql-42.6.0.jar放在Tomcat 10.1的./lib目录(符合JDBC驱动部署规范),但实际Web应用的类加载器加载了org.postgresql.util.LazyCleaner,该类启动的PostgreSQL-JDBC-Cleaner线程继承了关联Web应用类加载器的AccessControlContext,导致类加载器被永久引用无法GC,最终触发内存泄漏。

排查方向(你可能遗漏的点)

1. 驱动重复打包

检查你的Spring Boot应用包的WEB-INF/lib目录,确认是否存在postgresql-*.jar。如果有,Web应用类加载器会优先加载本地依赖,而非Tomcat公共类加载器中的驱动。解决方式:

  • Maven中给PostgreSQL依赖添加<scope>provided</scope>,避免打包进应用:
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.6.0</version>
        <scope>provided</scope>
    </dependency>
    
  • Gradle中将implementation 'org.postgresql:postgresql:42.6.0'改为compileOnly 'org.postgresql:postgresql:42.6.0'。

2. Tomcat类加载器配置异常

  • 检查conf/catalina.properties的common.loader配置,确认${catalina.base}/lib和${catalina.home}/lib在加载路径中(默认包含,若被修改会导致公共类加载器无法加载驱动)。
  • 检查Web应用的META-INF/context.xml或Tomcat全局conf/context.xml,是否存在强制指定应用类加载器加载驱动的配置。

3. 驱动类加载逻辑验证

org.postgresql.util.LazyCleaner的静态代码块会在类加载时启动清理线程。如果该类由Tomcat公共类加载器加载,线程关联的是公共类加载器,不会影响Web应用卸载;只有当类被应用类加载器加载时才会出问题。

  • 部署后用jstack查看PostgreSQL-JDBC-Cleaner线程的上下文类加载器:
    jstack <tomcat-pid> | grep -A 5 "PostgreSQL-JDBC-Cleaner"
    
    正常输出应显示org.apache.catalina.loader.StandardClassLoader类加载器,而非Web应用类加载器(如org.apache.catalina.loader.ParallelWebappClassLoader)。

验证步骤

  1. 移除应用包中的PostgreSQL驱动,仅保留Tomcat ./lib下的版本。
  2. 重启Tomcat,部署应用后检查线程的上下文类加载器。
  3. 多次部署/卸载应用,通过MAT确认Web应用类加载器是否能被GC回收。

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:25:53