[ 
https://issues.apache.org/jira/browse/WW-5537?focusedWorklogId=1010850&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1010850
 ]

ASF GitHub Bot logged work on WW-5537:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 23/Mar/26 09:15
            Start Date: 23/Mar/26 09:15
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #1632:
URL: https://github.com/apache/struts/pull/1632

   ## Summary
   
   Port of #1631 (Struts 6) to Struts 7, with Java 17 improvements.
   
   Fixes classloader/memory leaks that cause `OutOfMemoryError` (Metaspace) 
during Tomcat hot redeployment 
([WW-5537](https://issues.apache.org/jira/browse/WW-5537)):
   
   - Introduces `InternalDestroyable` / `ContextAwareDestroyable` interfaces 
with container-based discovery so static caches, daemon threads, and shared 
references are cleaned up when `Dispatcher.cleanup()` runs
   - Clears OGNL, Component, ScopeInterceptor, DefaultFileManager, DebugUtils, 
FreeMarker, and JSON plugin caches
   - Stops the `FinalizableReferenceQueue` daemon thread with proper `join()` 
and classloader cleanup
   - Replaces `ContainerHolder` plain `ThreadLocal` with generation-counter 
pattern (`AtomicLong`) for safe cross-thread invalidation during undeploy
   
   ### Java 17 improvements over Struts 6 (Java 8) version
   
   | Pattern | Struts 6 (Java 8) | Struts 7 (Java 17) |
   |---------|-------------------|-------------------|
   | Generation counter | `volatile long` with non-atomic `++` | `AtomicLong` 
(thread-safe) |
   | CachedContainer | Inner class | `record` |
   | Type checks | Old-style casts | Pattern matching `instanceof` |
   
   ### Changes
   
   | Area | What |
   |------|------|
   | Core | `InternalDestroyable` / `ContextAwareDestroyable` interfaces |
   | Core | 6 adapter classes: Component, OGNL, ScopeInterceptor, 
FinalizableReferenceQueue, FreeMarker, DebugUtils destroyables |
   | Core | `ContainerHolder` ThreadLocal → ThreadLocal + AtomicLong generation 
counter |
   | Core | `Dispatcher.cleanup()` refactored into focused destroy methods with 
container discovery |
   | Core | `FinalizableReferenceQueue`: volatile instance, join(5000), 
setContextClassLoader(null) |
   | Core | `ScopeInterceptor.clearLocks()`: synchronized block for thread 
safety |
   | Core | `PrepareOperations`: per-request `ContainerHolder.clear()` |
   | JSON plugin | `JSONCacheDestroyable` registered in `struts-plugin.xml` |
   | Showcase | `log4j-web` for proper Log4j2 lifecycle in servlet container |
   
   ## Test plan
   
   - [x] `DispatcherCleanupTest` — 8 tests verifying InternalDestroyable 
discovery and all static caches cleared after `dispatcher.cleanup()`
   - [x] `ContainerHolderTest` — 4 tests verifying store/get, clear, 
invalidateAll cross-thread and same-thread
   - [x] Full core test suite: 2903 tests passing
   - [x] JSON plugin test suite: passing
   - [ ] Manual verification: deploy WAR on Tomcat, redeploy 5+ times, confirm 
no Metaspace growth
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)




Issue Time Tracking
-------------------

    Worklog Id:     (was: 1010850)
    Time Spent: 0.5h  (was: 20m)

> 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: 0.5h
>  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)

Reply via email to