[
https://issues.apache.org/jira/browse/WW-5630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18084247#comment-18084247
]
Brian Andle edited comment on WW-5630 at 5/29/26 3:53 AM:
----------------------------------------------------------
[~lukaszlenart] we just had this come up in our instances as well and was
coming to report the same thing. Struts 6.8, Java 8 on Tomcat 9.0.118.
{code:java}
"Web Handler 1080" Id=1080 in RUNNABLE at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1160)
at
com.opensymphony.xwork2.util.ConfigParseUtil.validateClasses(ConfigParseUtil.java:76)
at
com.opensymphony.xwork2.util.ConfigParseUtil.toNewClassesSet(ConfigParseUtil.java:53)
at
com.opensymphony.xwork2.ognl.SecurityMemberAccess.useExcludedClasses(SecurityMemberAccess.java:465)
{code}
Blocks (as an example):
{code:java}
"Web Handler 1060" Id=1060 in BLOCKED on lock=java.lang.Object@2e614f4
owned by Web Handler 1080 Id=1080 at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1160)
at
com.opensymphony.xwork2.util.ConfigParseUtil.validateClasses(ConfigParseUtil.java:76)
at
com.opensymphony.xwork2.util.ConfigParseUtil.toNewClassesSet(ConfigParseUtil.java:53)
at
com.opensymphony.xwork2.ognl.SecurityMemberAccess.useDevModeExcludedClasses(SecurityMemberAccess.java:520)
{code}
and
{code:java}
"Web Handler 1050" Id=1050 in BLOCKED on lock=java.lang.Object@2e614f4
owned by Web Handler 1080 Id=1080
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1160)
at
com.opensymphony.xwork2.util.ConfigParseUtil.validateClasses(ConfigParseUtil.java:76)
at
com.opensymphony.xwork2.util.ConfigParseUtil.toNewClassesSet(ConfigParseUtil.java:53)
at
com.opensymphony.xwork2.ognl.SecurityMemberAccess.useExcludedClasses(SecurityMemberAccess.java:465)
{code}
Even with the Tomcat ParallelWebappClassLoader we end up in Tomcat
WebappClassLoaderBase a:
{code:java}
synchronized (JreCompat.isGraalAvailable() ? this : getClassLoadingLock(name))
{ {code}
Which ends up working it's way down the
useExcludedClasses/useDevModeExcludedClasses list (which is basically the same)
so you end up doubling the chance of two threads hitting the same class lookup
by name.
In my instance we ended up with 35 threads blocked (they eventually clear, but
performance suffers/"halts" until it does).
If you have heavy load and happen to hit the same class name lock we end up
blocking and we start to pile up.
I'd agree we should probably cache, maybe have a sized static cache of found
classes, maybe 50(?), in ConfigParseUtil to prevent any sort of mass contention.
Ideally, we could come up with a solution for Struts 6.x as well.
was (Author: JIRAUSER287474):
[~lukaszlenart] we just had this come up in our instances as well and was
coming to report the same thing. Struts 6.8, Java 8 on Tomcat 9.0.118.
{code:java}
"Web Handler 1080" Id=1080 in RUNNABLE at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1160)
at
com.opensymphony.xwork2.util.ConfigParseUtil.validateClasses(ConfigParseUtil.java:76)
at
com.opensymphony.xwork2.util.ConfigParseUtil.toNewClassesSet(ConfigParseUtil.java:53)
at
com.opensymphony.xwork2.ognl.SecurityMemberAccess.useExcludedClasses(SecurityMemberAccess.java:465)
{code}
Blocks (as an example):
{code:java}
"Web Handler 1060" Id=1060 in BLOCKED on lock=java.lang.Object@2e614f4
owned by Web Handler 1080 Id=1080 at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1160)
at
com.opensymphony.xwork2.util.ConfigParseUtil.validateClasses(ConfigParseUtil.java:76)
at
com.opensymphony.xwork2.util.ConfigParseUtil.toNewClassesSet(ConfigParseUtil.java:53)
at
com.opensymphony.xwork2.ognl.SecurityMemberAccess.useDevModeExcludedClasses(SecurityMemberAccess.java:520)
{code}
and
{code:java}
"Web Handler 1050" Id=1050 in BLOCKED on lock=java.lang.Object@2e614f4
owned by Web Handler 1080 Id=1080
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1160)
at
com.opensymphony.xwork2.util.ConfigParseUtil.validateClasses(ConfigParseUtil.java:76)
at
com.opensymphony.xwork2.util.ConfigParseUtil.toNewClassesSet(ConfigParseUtil.java:53)
at
com.opensymphony.xwork2.ognl.SecurityMemberAccess.useExcludedClasses(SecurityMemberAccess.java:465)
{code}
Even with the Tomcat ParallelWebappClassLoader we end up in Tomcat
WebappClassLoaderBase a:
{code:java}
synchronized (JreCompat.isGraalAvailable() ? this : getClassLoadingLock(name))
{ {code}
Which ends up working it's way down the
useExcludedClasses/useDevModeExcludedClasses list (which is basically the same)
so you end up doubling the chance of two threads hitting the same class lookup
by name.
In my instance we ended up with 35 threads blocked.
If you have heavy load and happen to hit the same class name lock we end up
blocking and we start to pile up.
I'd agree we should probably cache, maybe have a sized static cache of found
classes, maybe 50(?), in ConfigParseUtil to prevent any sort of mass contention.
Ideally, we could come up with a solution for Struts 6.x as well.
> 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: 7.3.0
>
> Attachments: image-2026-05-20-16-37-00-000.png
>
> Time Spent: 10m
> 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)