[BUG] ShenyuPluginClassLoaderHolder.createPluginClassLoader non-atomic check/remove/put race
- Dominant language
- Java
- Stars
- 8.8k
- Forks
- 3.1k
- Avg merge
- 7d 1h
- Merged PRs (30d)
- 85
Description
- Severity: Medium-High
- Location:
`shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoaderHolder.java:51-58` (same pattern at `:66-69`)
-
Description:
`if (pluginCache.containsKey(jarKey)) { pluginCache.remove(jarKey).close(); } pluginCache.put(jarKey, shenyuPluginClassLoader);` — three separate `ConcurrentHashMap` ops, not atomic. Two threads creating a classloader for the same `jarKey` race: T1 removes+closes old; T2's `containsKey` returns false so it skips close; T2 `put`s CL2; T1 `put`s CL1 overwriting CL2. CL2 is orphaned — never closed, its Spring beans never destroyed — and lost to callers.
-
Impact:
Classloader + Spring bean leak; the returned classloader can be one whose beans were already destroyed by a concurrent `close()`.
-
Suggested fix:
Use `pluginCache.compute(jarKey, (k, old) -> { if (old != null) old.close(); return shenyuPluginClassLoader; })`.
-
Confidence: Medium-High
- Related existing: none
---
_Identified during the 2026-08-02 deep re-scan; full list in [`docs/scan2-2026-08-02/06-medium-tiers.md`](docs/scan2-2026-08-02/06-medium-tiers.md)._
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoaderHolder.java:51-58 and compare the same pattern at :66-69. Trace createPluginClassLoader and examine how pluginCache entries are closed and replaced under concurrent calls. Done means replacement is atomic, the superseded loader is closed exactly once, and concurrent callers cannot receive a closed or lost classloader.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100