commit | 882c71d3306cb6d43ab91b3a4c3d6091d48ab922 | [log] [tgz] |
---|---|---|
author | abcpro1 <abcpro11051@disroot.org> | Sat Nov 12 20:56:43 2022 +0000 |
committer | abcpro1 <abcpro11051@disroot.org> | Sat Nov 12 20:56:43 2022 +0000 |
tree | cbbacb0265f3de5ff9b89e53f7eb054f4644d112 | |
parent | 55ea1e0821db72bc66c2d555069f4338f224ea0b [diff] |
Jersey 2: Solve a memory leak There was a memory leak in org.springframework.web.context.ContextLoader where objects were being inserted into a map but never removed from it. The map is [this](https://github.com/spring-projects/spring-framework/blob/v5.3.23/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java#L152-L156). This map matches a WebApplicationContext to the current thread class loader The insertion to the map happens during a web application deployment [here](https://github.com/spring-projects/spring-framework/blob/v5.3.23/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java#L302). The thread class loader is set prior to this operation by org.glassfish.grizzly.servlet.WebappContext [here](https://github.com/eclipse-ee4j/grizzly/blob/2.4.4/modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/WebappContext.java#L2080) Finally, when the web application is being destroyed; The WebApplicationContext inserted earlier is supposed to be removed from the map [here](https://github.com/spring-projects/spring-framework/blob/v5.3.23/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java#L526). But, the thread class loader this time is different from when the insertion occurred. This is a bug in Grizzly, as you can see [here](https://github.com/eclipse-ee4j/grizzly/blob/2.4.4/modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/WebappContext.java#L2106-L2127) the thread class loader is not set unlike during initialization. This is the cause of the discrepancy of the thread class loader between initialization and destruction. A straightforward solution was implemented in this commit, which is to set the thread class loader before destruction to the class loader that was active during initialization. In the future, this issue needs be solved in the Grizzly project.
diff --git a/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java b/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java index 578c94e..5dd00a0 100644 --- a/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java +++ b/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java
@@ -1,5 +1,7 @@ package de.ids_mannheim.korap.config; +import javax.servlet.ServletContextEvent; + import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; @@ -14,9 +16,31 @@ public static WebApplicationContext applicationContext; + private ClassLoader contextClassLoader; + public StaticContextLoaderListener () { super(applicationContext); } + @Override + public void contextInitialized(ServletContextEvent event) { + contextClassLoader = Thread.currentThread().getContextClassLoader(); + super.contextInitialized(event); + } + @Override + public void contextDestroyed(ServletContextEvent event) { + // Perform the destruction with the same contextual ClassLoader that was present + // during initialization. + // This a workaround for a bug in org.glassfish.grizzly.servlet.WebappContext + // that causes a memory leak in org.springframework.web.context.ContextLoader. + // This logic should be moved to WebappContext.contextDestroyed(). Until this + // is fixed in Grizzly; This is a good solution. + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(contextClassLoader); + + super.contextDestroyed(event); + + Thread.currentThread().setContextClassLoader(loader); + } }