Jose Miguel created WW-5667:
-------------------------------
Summary: Performance Issue: SecurityMemberAccess re-parses
excluded packages/classes config string on every OGNL access — O(n)
String.split per request
Key: WW-5667
URL: https://issues.apache.org/jira/browse/WW-5667
Project: Struts 2
Issue Type: Bug
Reporter: Jose Miguel
In stress test is consuming 9% of a server with 4 CPUs.
**Struts version:** 7.2.1
**JDK:** 21 (OpenJDK ms-21.0.7)
**JVM flags:** Payara 7.2026.6
**Summary:**
`SecurityMemberAccess.isClassBelongsToPackages()` and the related
`useExcludedPackageNames()` / `useExcludedClasses()` methods call
`ConfigParseUtil.toNewPackageNamesSet()` / `toNewClassesSet()` on every
OGNL member-access check, which calls `String.split()` and builds a new
`HashSet` each time from the raw config string.
Under moderate load (preprod server, ~20% Payara CPU) this accounts for
~9% of all RUNNABLE CPU samples in a 2-minute JFR profile.
**Stack traces (JFR ExecutionSamples, STATE_RUNNABLE):**
Sample 1:
java.lang.String.split(String)
SecurityMemberAccess.isClassBelongsToPackages(Class, Set) :390
SecurityMemberAccess.isExcludedPackageNames(Class) :386
SecurityMemberAccess.isPackageExcluded(Class) :371
Sample 2:
HashMap.put / HashSet.add
ConfigParseUtil.toNewPackageNamesSet(Collection, String) :138
SecurityMemberAccess.useExcludedPackageNames(String) :446
**Proposed fix:**
Cache the parsed `Set<String>` in `SecurityMemberAccess` as a field.
Rebuild it only when the raw config string reference changes (compare
with `==` or store the last-seen string). Since the excluded-packages
config is set once at startup and never changes at runtime, the cache
never needs invalidation in practice.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)