google / google/guice

[Bug] Memory Leak Risk in SingletonScope via Anonymous Provider (Implicit Outer Reference)

Open
#1,929 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
12.7k
Forks
1.7k
Avg merge
11m
Merged PRs (30d)
2

Description

### Issue Summary
The `scope()` method in `com.google.inject.internal.SingletonScope` returns an anonymous `Provider` instance. This architectural choice introduces a structural memory leak risk, specifically the "Deadly Embrace" pattern associated with non-static inner classes.

### Root Cause Analysis
In Java, the anonymous `Provider` implicitly holds a strong reference to its enclosing instance (`SingletonScope.this`). Guice's internal context management relies heavily on `ThreadLocal` structures (e.g., for cycle detection locks).

When this anonymous `Provider` is captured within a thread-bound context, it establishes a persistent retention chain:
`Thread -> ThreadLocalMap -> Anonymous Provider (Inner) -> SingletonScope (Outer)`.

### Impact
In environments utilizing thread pools (where threads are long-lived), this reference chain prevents the Garbage Collector from reclaiming the `SingletonScope` and its associated injector graph. This results in an unresolvable topological black hole ("拓扑环状黑洞") causing severe memory leaks over time.

### Proposed Solution
Refactor the anonymous `Provider` inside the `scope()` method into a `static` nested class. Any state required from the `SingletonScope` should be explicitly passed via the constructor. This will break the implicit strong reference to `SingletonScope.this` and allow the GC to function correctly.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.