Tomcat 7 WeaAppClassLoader 与 Jersey 2 的泄漏

Tomcat 7 WeaAppClassLoader leak with Jersey 2

我 运行 使用以下配置进入明显的 ClassLoader 泄漏:

我有一个简单的应用程序:

应用程序配置:

@ApplicationPath("/service")
public class ApplicationConfig extends Application {
    
    public ApplicationConfig() {
    }
    
    @Override
    public Set<Class<?>> getClasses(){
        Set<Class<?>> resources = new java.util.HashSet<>();
        
        resources.add(org.mdeggers.cplanapi.resource.CostInfoResource.class);
        resources.add(org.mdeggers.cplanapi.resource.InstituteInfoResource.class);
        resources.add(org.mdeggers.cplanapi.resource.InstituteTypeInfoResource.class);
        
        resources.add(org.mdeggers.cplanapi.mapper.NotFoundExceptionMapper.class);
        
        return resources;
    }
}

三个资源之一:

@Path("/v1/inst")
public class InstituteInfoResource {

    public InstituteInfoResource() {
    }

    @GET
    @Path("info")
    @Produces({MediaType.APPLICATION_JSON})
    public InstituteContainer getNationalList() {
        InstituteInfo instituteinfo = new InstituteInfo();
        return instituteinfo.getNational();
    }

    @GET
    @Path("info/{ state : [A-Z]{2} }")
    @Produces({MediaType.APPLICATION_JSON})
    public InstituteContainer getStateList(@PathParam("state") String state) {
        InstituteInfo instituteinfo = new InstituteInfo();
        return instituteinfo.getState(state);
    }
}

InstituteInfo class 是一个 DAO,它向 MySQL 数据库和 returns 包含信息的容器发出请求。

一切正常,但在取消部署 Tomcat 管理器时抱怨卸载 Web 应用程序后出现泄漏。

在 Eclipse MAT 中执行堆转储并使用以下 OQL 查看它表明应用程序仍然驻留在内存中,started=false。

SELECT wcl.contextName.toString() AS contextName,
   wcl.started AS started,
   wcl.@retainedHeapSize AS retainedSize
FROM org.apache.catalina.loader.WebappClassLoader wcl
contextName started retainedSize
/cplanapi false 586,720
/docs true 46,664
/host-manager true 47,288
/manager true 47,392
/examples true 85,432
ROOT true 46,912

cplanapi 的 GC 根是:

class com.sun.naming.internal.ResourceManager       
'- propertiesCache java.util.WeakHashMap                         
   '- table java.util.WeakHashMap$Entry[16]                      
      '- [13] java.util.WeakHashMap$Entry                         
         '- referent org.apache.catalina.loader.WebappClassLoader

这发生在 Windows 和 Linux 上,以及上述 JRE 和 Java 1.8.0_202.

任何有关如何解决此问题的想法都将不胜感激。

启动日志 (JRE 11)

Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server version name:   Apache Tomcat/7.0.107
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server built:          Nov 18 2020 12:18:55 UTC
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server version number: 7.0.107.0
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Name:               Windows 10
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Version:            10.0
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Architecture:          amd64
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Java Home:             D:\Programs-x64\Java\jdk-11.0.10+9-jre
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: JVM Version:           11.0.10+9
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: JVM Vendor:            AdoptOpenJDK
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: CATALINA_BASE:         D:\Programs\Apache\apache-tomcat-7.0.107
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: CATALINA_HOME:         D:\Programs\Apache\apache-tomcat-7.0.107
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.util.logging.config.file=D:\Programs\Apache\apache-tomcat-7.0.107\conf\logging.properties
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcom.sun.management.jmxremote
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcom.sun.management.jmxremote.port=9005
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcom.sun.management.jmxremote.ssl=false
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcom.sun.management.jmxremote.authenticate=false
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -DRDS_HOSTNAME=localhost
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dignore.endorsed.dirs=
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcatalina.base=D:\Programs\Apache\apache-tomcat-7.0.107
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcatalina.home=D:\Programs\Apache\apache-tomcat-7.0.107
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.io.tmpdir=D:\Programs\Apache\apache-tomcat-7.0.107\temp
Jan 31, 2021 10:09:19 AM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: Loaded Apache Tomcat Native library [1.2.25] using APR version [1.7.0].
Jan 31, 2021 10:09:19 AM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Jan 31, 2021 10:09:19 AM org.apache.catalina.core.AprLifecycleListener initializeSSL
INFO: OpenSSL successfully initialized [OpenSSL 1.1.1g  21 Apr 2020]
Jan 31, 2021 10:09:19 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-apr-8080"]
Jan 31, 2021 10:09:19 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-apr-127.0.0.1-8009"]
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 644 ms
Jan 31, 2021 10:09:19 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Catalina]
Jan 31, 2021 10:09:19 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.107
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\docs]
Jan 31, 2021 10:09:19 AM org.apache.catalina.startup.TldConfig execute
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jan 31, 2021 10:09:20 AM org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
WARNING: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [457] milliseconds.
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\docs] has finished in [905] ms
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\examples]
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.TldConfig execute
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\examples] has finished in [344] ms
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\host-manager]
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.TldConfig execute
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\host-manager] has finished in [146] ms
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\manager]
Jan 31, 2021 10:09:20 AM org.apache.catalina.startup.TldConfig execute
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jan 31, 2021 10:09:21 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\manager] has finished in [148] ms
Jan 31, 2021 10:09:21 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\ROOT]
Jan 31, 2021 10:09:21 AM org.apache.catalina.startup.TldConfig execute
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jan 31, 2021 10:09:21 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\ROOT] has finished in [136] ms
Jan 31, 2021 10:09:21 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-apr-8080"]
Jan 31, 2021 10:09:21 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-apr-127.0.0.1-8009"]
Jan 31, 2021 10:09:21 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 1766 ms

部署

Jan 31, 2021 10:09:49 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\cplanapi.war]
Jan 31, 2021 10:09:50 AM org.apache.catalina.startup.TldConfig execute
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jan 31, 2021 10:09:53 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deployment of web application archive [D:\Programs\Apache\apache-tomcat-7.0.107\webapps\cplanapi.war] has finished in [3,558] ms

取消部署

Jan 31, 2021 10:10:27 AM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context [/cplanapi]

关机

Jan 31, 2021 10:10:37 AM org.apache.catalina.core.StandardServer await
INFO: A valid shutdown command was received via the shutdown port. Stopping the Server instance.
Jan 31, 2021 10:10:37 AM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["http-apr-8080"]
Jan 31, 2021 10:10:37 AM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["ajp-apr-127.0.0.1-8009"]
Jan 31, 2021 10:10:37 AM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service [Catalina]
Jan 31, 2021 10:10:37 AM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-apr-8080"]
Jan 31, 2021 10:10:37 AM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["ajp-apr-127.0.0.1-8009"]
Jan 31, 2021 10:10:37 AM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-apr-8080"]
Jan 31, 2021 10:10:37 AM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["ajp-apr-127.0.0.1-8009"]

Web 应用程序中似乎没有悬空的东西。

在 Mark Thomas 在 Tomcat 邮件列表中发表了一些评论后,我设法找到了问题所在(有两个)。诀窍是在 GC ROOT 分析中排除软引用以揭示真正的罪魁祸首。

Jackson Buffer leak

错误报告中给出了该问题的修复。基本上,您必须设置一个系统 属性,并添加一个 servlet 上下文侦听器以在关闭 Web 应用程序之前清除缓冲区。

log4j2 JMX leak

这被标记为关闭/修复,但似乎不是。通过使用另一个系统关闭 log4j 的 JMX(现在)属性 修复了这个问题。