Skip to content

War deployment in standalone Tomcat causes memory leak (Metaspace) #27987

@AlexieKA

Description

@AlexieKA

Steps to reproduce:

  1. Create an empty application in https://start.spring.io/ with the following parameters:
  • Spring Boot 2.5.4
  • Packaging War
  • Java 11
  • Spring Web
  1. Build the application (gradle build)
  2. Deploy the resulting war in a standalone Tomcat
  3. Perform several (5-10) restarts of the application with Tomcat manager
  4. As a result, we observe a metaspace leak (if a value of XX:MaxMetaspaceSiz is set and was reached, we get an exception)

Analysis

  1. Create Heap Dump (for example, using jvisualvm)
  2. Open the dump file with jvisualvm or MemoryAnalyzer
  3. Select all objects of ParallelWebappClassLoader type
  4. The number of objects is equal to the number of restarts plus active application instances in Tomcat
  5. Select «Path to GC Root» for inactive ParallelWebappClassLoader
  6. We can see the Thread (reference to ParallelWebappClassLoader) is stored in ApplicationShutdownHooks. Because of this reference, the GC cannot delete this ParallelWebappClassLoader instance and free metaspace

Causes

  1. The thread that holds ParallelWebappClassLoader is created in the constructor of the class SpringApplicationShutdownHook (line 74)
  2. The object of SpringApplicationShutdownHook is created when loading the SpringApplication type (line 203)
  3. Since every restart of the application (from the tomcat admin panel) create new classloader and initialize SpringApplication type, which causes memory leak.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: regressionA regression from a previous release

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions