Skip to content

Make SingletonScope scoped Provider a static nested class - #1941

Open
arimu1 wants to merge 1 commit into
google:masterfrom
arimu1:fix/1929-singleton-scope-static-provider
Open

Make SingletonScope scoped Provider a static nested class#1941
arimu1 wants to merge 1 commit into
google:masterfrom
arimu1:fix/1929-singleton-scope-static-provider

Conversation

@arimu1

@arimu1 arimu1 commented Aug 1, 2026

Copy link
Copy Markdown

Summary

SingletonScope.scope() previously returned an anonymous (non-static) Provider. In Java, that always retains an implicit outer reference to SingletonScope.this, even though the provider only needs key and creator (plus static scope state).

If such a provider is retained from a long-lived structure (e.g. thread pool / ThreadLocal context), that outer reference can keep the scope instance reachable longer than necessary.

This change:

  • Replaces the anonymous provider with a private static nested SingletonProvider
  • Passes key / creator explicitly through the constructor
  • Preserves singleton semantics (double-checked locking, cycle locks, circular proxies, null sentinel, toString)

Fixes #1929

Test plan

  • mvn -pl core test -Dtest=ScopesTest,CircularDependencyTest,EagerSingletonTest (JDK 21)
    • ScopesTest 35/35
    • CircularDependencyTest 24/24
    • EagerSingletonTest 4/4
  • New testSingletonScopedProviderDoesNotRetainOuterScope asserts static nested class and no this$ synthetic field, plus still caches instances

Notes

  • Google CLA may be required for this contribution (human sign-off if the CLA bot flags it).

Anonymous providers retain SingletonScope.this, which can pin the scope
if a provider is held from a long-lived thread-local. Pass key/creator
explicitly via the constructor instead.

Fixes google#1929
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant