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

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

                Author: ASF GitHub Bot
            Created on: 12/Jun/26 05:56
            Start Date: 12/Jun/26 05:56
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart commented on code in PR #1721:
URL: https://github.com/apache/struts/pull/1721#discussion_r3401034501


##########
core/src/main/java/org/apache/struts2/util/ConfigParseUtil.java:
##########
@@ -33,6 +35,15 @@
 import static org.apache.commons.lang3.StringUtils.strip;
 
 public class ConfigParseUtil {
+    // Size the cache to prevent excessive memory usage in environments with 
many classloaders and/or large numbers of classes being validated.
+    // While still providing a reasonable caching benefit for common cases 
(e.g. multiple Struts instances in the same container, or multiple calls to 
validate the same class across different containers).
+    private static final int MAX_CLASS_CACHE_SIZE = 50;
+
+    private static final Cache<ClassLoader, Cache<String, Class<?>>> 
VALIDATED_CLASS_CACHE = Caffeine.newBuilder()
+            .weakKeys()
+            .weakValues()

Review Comment:
   Non-blocking: `weakValues()` on the **outer** cache makes the per-loader 
inner `Cache` (the *value*) weakly reachable. Nothing else holds a strong 
reference to an inner cache, so GC can reclaim it while its `ClassLoader` key 
is still alive and in active use — which intermittently empties the cache and 
partially defeats the optimization under memory pressure.
   
   `weakKeys()` already guarantees the entry is dropped as soon as the loader 
becomes unreachable, so the outer `weakValues()` isn't needed for leak-safety. 
Suggest removing it from the **outer** builder (keep `weakKeys()` here and the 
`weakValues()` on the inner cache at line 97, which correctly lets unreferenced 
`Class` values be reclaimed). Correctness is fine either way; this is purely 
about cache effectiveness.
   
   Also minor: with the redesign `maximumSize(50)` now bounds the number of 
*classloaders*, not classes — the `MAX_CLASS_CACHE_SIZE` comment above still 
describes bounding classes.





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

    Worklog Id:     (was: 1024804)
    Time Spent: 40m  (was: 0.5h)

> Performance Issue SecurityMemberAccess
> --------------------------------------
>
>                 Key: WW-5630
>                 URL: https://issues.apache.org/jira/browse/WW-5630
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Value Stack
>         Environment: Payara 7
>            Reporter: Jose Miguel
>            Priority: Major
>             Fix For: 6.11.0, 7.2.0
>
>         Attachments: image-2026-05-20-16-37-00-000.png
>
>          Time Spent: 40m
>  Remaining Estimate: 0h
>
> The Security hardening introduced some performance issues in a system 
> multibranch (payara) where one single action is used to process thousand of 
> files per minute. The action is using exctly same calls, parameters, and 
> classes every call.
> Every call is loading classes, so, blocks the ClassLoader as can be seen in 
> JDK Mission Control.
> There's no way to avoid this issue, played with several confi parameters, 
> with no luck.
> Checking code, is not cached, it's suggested to cache The validation of 
> classes, to avoid validate again and again the same class. the  classes 
> mostly validated again and again are: java.lang.Process
> org.apache.struts2.ActionContext
> java.lang.Runtime
> java.lang.Thread
> java.lang.ThreadLocal
>  
> public static Set<Class<?>> validateClasses(Set<String> classNames, 
> ClassLoader validatingClassLoader) throws ConfigurationException {
> Set<Class<?>> classes = new HashSet<>();
> for (String className : classNames) {
> try {
> classes.add(validatingClassLoader.loadClass(className));
> } catch (ClassNotFoundException e) {
> throw new ConfigurationException("Cannot load class for exclusion/exemption 
> configuration: " + className, e);
> }
> }
> return classes;
> }
>  
> !image-2026-05-20-16-37-00-000.png!



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to