arextest / arextest/arex-agent-java

[Bug/设计疑问] ForkJoinTask 上下文缓存(WeakCache/CAPTURED_CACHE)依赖 GC 清理而非显式 remove,在 JDK 21 下导致堆内存无界增长

Open
#626 1 comment 0 reactions 0 assignees View on GitHub
bug :lady_beetle:
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.