[
https://issues.apache.org/jira/browse/WW-5537?focusedWorklogId=1010818&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1010818
]
ASF GitHub Bot logged work on WW-5537:
--------------------------------------
Author: ASF GitHub Bot
Created on: 23/Mar/26 06:26
Start Date: 23/Mar/26 06:26
Worklog Time Spent: 10m
Work Description: lukaszlenart opened a new pull request, #1631:
URL: https://github.com/apache/struts/pull/1631
## Summary
- Fixes classloader/memory leaks that cause `OutOfMemoryError` (Metaspace)
during Tomcat hot redeployment
([WW-5537](https://issues.apache.org/jira/browse/WW-5537))
- Introduces `InternalDestroyable` interface with container-based discovery
so static caches, daemon threads, and shared references are cleaned up when
`Dispatcher.cleanup()` runs
- Clears OGNL, Component, ScopeInterceptor, DefaultFileManager, FreeMarker,
and JSON plugin caches; stops the `FinalizableReferenceQueue` daemon thread;
replaces `ContainerHolder` `ThreadLocal` with `volatile`
## Changes
| Area | What |
|------|------|
| Core | `InternalDestroyable` / `ContextAwareDestroyable` interfaces |
| Core | `ComponentCacheDestroyable`, `OgnlCacheDestroyable`,
`ScopeInterceptorCacheDestroyable`, `FinalizableReferenceQueueDestroyable`,
`FreemarkerCacheDestroyable` |
| Core | `ContainerHolder` ThreadLocal → volatile |
| Core | `Dispatcher.cleanup()` refactored into focused destroy methods |
| JSON plugin | `JSONCacheDestroyable` registered in `struts-plugin.xml` |
| Tests | `DispatcherCleanupLeakTest` (8 tests),
`FinalizableReferenceQueueTest` |
## Test plan
- [x] `DispatcherCleanupLeakTest` — verifies each static cache is cleared
after `dispatcher.cleanup()`
- [x] `FinalizableReferenceQueueTest` — verifies daemon thread stops and
singleton is nulled
- [ ] Manual verification: deploy HelloWorld WAR on Tomcat 9, redeploy 5+
times, confirm no Metaspace growth via `jmap`/MAT
- [ ] Run full CI suite
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Issue Time Tracking
-------------------
Worklog Id: (was: 1010818)
Remaining Estimate: 0h
Time Spent: 10m
> Memory Leak
> ------------
>
> Key: WW-5537
> URL: https://issues.apache.org/jira/browse/WW-5537
> Project: Struts 2
> Issue Type: Bug
> Components: Core
> Affects Versions: 6.7.0
> Environment: JDK 17
> Tomcat 9
> Reporter: Andrea Vettori
> Assignee: Lukasz Lenart
> Priority: Major
> Fix For: 6.9.0, 7.2.0
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> Struts is leaking memory when a WAR is hot deployed in Tomcat: for each hot
> deploy some classes remain in memory instead of being garbage collected. For
> big applications this causes OOM memory exceptions very quickly for Meatspace
> exhaustion because the entire class loader of the app is not released.
> For testing the HelloWorld app from struts-examples can be used. Deploy the
> war in tomcat as the only web app in the server. For each "reload" (from
> Tomcat manager) or simply copying the war file over the deployed one, taking
> a memory dump (with jmap) and looking at the content with a memory profiler
> (such as Eclipse MAT) shows that there is one ApplicationContext class for
> each hot deploy instead of just one.
>
> The problem is present in version 6.7.4-SNAPSHOT of Feb 28th.
>
> If the server can be restarted at each deploy the problem is obviously not a
> real problem. However if a tomcat instance contains more than one application
> being able to hot deploy a single one is very useful as it does not force all
> apps down for the server restart.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)