apache / apache/shenyu

[BUG] ShenyuClientProxyFactory caches proxies in static ConcurrentMap keyed by apiClass — stale proxy + ApplicationContext leak across restarts

Open
#6,856 1 comment 0 reactions 0 assignees View on GitHub
priority: medium sdk type: bug
Dominant language
Java
Stars
8.8k
Forks
3.1k
Avg merge
7d 1h
Merged PRs (30d)
85

Description

## Description
`PROXY_CACHE` is a `static` `ConcurrentMap, Object>` that is never cleared. `createProxy` does a `containsKey`-then-`get` fast path, else `synchronized(apiClass)` builds a `ShenyuClientInvocationHandler` (which captures the `ApplicationContext` and the per-bean `ShenyuClientFactoryBean` and resolves `applicationContext.getBean(ShenyuSdkClient.class)` at construction) and stores it in the static map. The first `ApplicationContext` to build a proxy for a given interface wins; every subsequent context (Spring Boot devtools restart, repeated `@SpringBootTest` contexts) receives the cached proxy bound to the now-closed previous context.

## Location
- `shenyu-sdk/shenyu-sdk-spring/src/main/java/org/apache/shenyu/sdk/spring/proxy/ShenyuClientProxyFactory.java:36,51-61`
- `shenyu-sdk/shenyu-sdk-spring/src/main/java/org/apache/shenyu/sdk/spring/proxy/ShenyuClientInvocationHandler.java:65-74,99-114`

## Impact
After a context restart the proxy's captured `ShenyuSdkClient` and `ApplicationContext` belong to the dead context (broken/leaked HTTP client, stale url/path from the old `ShenyuClientFactoryBean`). The static cache also holds a strong reference to the closed `ApplicationContext` and all beans it transitively captured, preventing GC of closed contexts → memory growth across restarts.

## Suggested fix
Key the cache per-context (or drop the static cache and rely on `FactoryBean.isSingleton()` + Spring's own singleton cache); alternatively clear `PROXY_CACHE` on context close / make it an instance field wired to the registrar.

## Related existing
None — distinct from #6787 (static URIS list in register-client `ShenyuClientURIExecutorSubscriber`, different class/module) and #6729 (GW-SPI-7, ExtensionLoader pinned ClassLoader).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with ShenyuClientProxyFactory.java, especially PROXY_CACHE and createProxy, then read ShenyuClientInvocationHandler.java to trace the captured ApplicationContext and ShenyuSdkClient. Exercise proxy creation across repeated Spring application contexts and verify that a new context does not receive a proxy from a closed one. Done means stale proxies and strong references to closed contexts are no longer retained.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.