arextest / arextest/arex-agent-java
[Bug/设计疑问] ForkJoinTask 上下文缓存(WeakCache/CAPTURED_CACHE)依赖 GC 清理而非显式 remove,在 JDK 21 下导致堆内存无界增长
- Dominant language
- Java
- Stars
- 564
- Forks
- 140
- Avg merge
- 36m
- Merged PRs (30d)
- 2
Description
### Search before asking
- [x] I have searched the existing [issues](https://github.com/arextest/arex-agent-java/issues) before asking.
### AREX Test Service
AREX Java Agent (arextest/arex-agent-java)
### Current Behavior
WeakReferenceKey + ArexThreadLocal.Transmitter.Snapshot + HashMap 对象增加,内存持续上涨
### Expected Behavior
我希望了解:为何 ForkJoinTask 插桩设计为依赖弱引用 + `WeakCache.check()` 做驱逐,而不是在任务执行结束时显式 remove?** 在我们的环境中,该设计会导致缓存无界增长。
### 当前设计
**1. ForkJoinTask 构造时 put**
`ForkJoinTaskConstructorInstrumentation` 捕获上下文并写入静态缓存:
```java
// ForkJoinTaskConstructorInstrumentation.ConstructorAdvice
final Object captured = ArexThreadLocal.Transmitter.capture();
if (captured != null) {
Cache.CAPTURED_CACHE.put(task, captured);
}
2. exec/run 时 get + replay
// ForkJoinTaskInstrumentation.ExecAdvice.onEnter
final Object captured = Cache.CAPTURED_CACHE.get(task);
backup = ArexThreadLocal.Transmitter.replay(captured);
3. 退出时仅 restore,无 remove
// ForkJoinTaskInstrumentation.ExecAdvice.onExit
ArexThreadLocal.Transmitter.restore(backup);
// 缺少:Cache.CAPTURED_CACHE.remove(task);
4. 驱逐依赖 WeakCache.check() + GC
// WeakCache:Key 为 WeakReference,Value(Snapshot)为强引用
void check() {
while ((reference = poll()) != null) {
target.remove(reference); // 仅当 ForkJoinTask 被 GC 并入队后
}
}
### Steps To Reproduce
JDK 21 / 虚拟线程背景
我们的复现环境(Spring Boot + JDK 21):
@GetMapping("/test1")
public String hello() {
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 1; i <= 10; i++) {
executor.submit(() -> log.info("hello: {}", n));
}
}
return "success";
}
### Anything else
_No response_
### Are you willing to submit a pull request to fix on your own?
- [ ] Yes I am willing to submit a pull request on my own!
Contributor guide
No contributing guide indexed for this repository
Research direction
Read ForkJoinTaskConstructorInstrumentation.ConstructorAdvice, ForkJoinTaskInstrumentation.ExecAdvice, and WeakCache first, tracing how CAPTURED_CACHE stores and evicts task snapshots. Run the JDK 21 virtual-thread reproduction and verify the cache lifecycle. Done means the eviction behavior is explained and there is an agreed decision on cleanup or documentation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- devtools, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 42/100