JDK-6501120 : (thread) Existing constructors lead to pinned copies of inheritable thread locals
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic
  • CPU: generic
  • Submitted: 2006-12-06
  • Updated: 2022-06-19
  • Resolved: 2022-06-19
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
It appears that currently there's no way to create a thread
without inheriting inheritable Thread Local Storage (duh), and context
class loader.

This is unfortunate as jdk spawns a lot of long-lived
threads (for example, all shutdown hooks are threads), and
most of them created from user threads, and thus could cause
leaks both by holding on to TLS and context class loader.
(The latter could be addressed by resetting the CCS)

Comments
A new constructor was added to Thread in Java 9 that allows opt-ing out of inheriting the initial value of inheritable thread locals from the constructing thread. The new Thread.Builder in Java 19 also supports configuring a thread builder that does the same. In addition, the thread Context ClassLoader has been been re-specified in Java 19 to work like an inheritable thread local so there is control on whether it is inherited from the constructing thread. So I think we can close this issue now.
19-06-2022

EVALUATION Further discussion made it clear that fixing existing Java SE versions is the overriding priority. So this request has to be changed to a defect report aimed at updates of existing JDK versions rather than an enhancement request that could offer a new public API.
13-12-2006

EVALUATION Providing a way for threads that may never terminate to avoid having a copy of the parent thread's InheritableThreadLocal instances would address a problem that currently has no solution in some circumstances: when the "heritage" of the creating thread with respect to inheritable thread locals cannot be controlled or even determined. The former case is sometimes inevitable with reuse of Thread instances, while the latter case is the dilemma faced by middleware that has no means of knowing about the parent invoking its thread creating methods (such as with request 6489540). However, providing additional API support that overlaps Thread.setContextClassLoader seems less useful, especially since any circumstance calling for the proposed "disinherited Thread" constructor is a natural point where consideration should be given to the context classloader and whether the new thread needs to inherit that or not. Tying the nulling of the context classloader together with suppressing local (copy) inheritance is likely to create an additional scenario in which developers can't get the behavior their application requires. That is, they may need to avoid one form of inheritance while needing to preserve the other. So this request should probably preserve both choices. And limiting the scope would make this proposal more similar to one contained in request 4219095. A single new Thread constructor or suitably named static factory method would work for some use cases, but not for others. A new instance method for Thread that removes inheritable locals would be a more general solution, and is worth exploring. However the requirements of this request's description as well as 6489540 are clear and so if something beyond a "no inheritance constructor" is ruled out it doesn't imply nothing should be done about the current use case. So what follows is a proposal that might be scaled back as more information becomes available. Also, a security permission specific to any control over inheritance seems warranted in case there are security ramifications to someone's inheritable thread local variable and they currently assume that this capability isn't possible. A new method such as Thread.removeInheritableThreadLocals() (a better name would be welcome!), in combination with setContextClassLoader, would allow upstream code to get a managed Thread instance into a known state such that if it subsequently spawns a child thread that child is free of "local baggage", assuming it hasn't instantiated any InheritableThreadLocal objects in the meantime. Having a new constructor or factory that suppresses copying of inherited locals isn't actually a solution for the general case involving reuse of Threads as the managed threads themselves would tend to accumulate inheritable locals and the onus would be on code creating child threads to judge whether inheritance must be avoided or not. With a means of removing inheritables code such as Java2D of CR 6489540 that spawns child threads could use either approach to prevent or prune undesirable local state. The overhead of a inheritable removal method would tend to be minimal, as there are no inheritable locals to remove in the common case. On the other hand, the implication of InheritableThreadLocal.childValue being executed at child Thread creation time is a drawback. Finally, a removal method would allow clear and simple documentation that steers clear of the already complex collection of existing Thread constructors. Keeping this new feature away from Thread construction also makes it easier to reason about possible implications and would hopefully minimize implications due to expanding the current constructor set. But to reiterate, addressing the specific use case described is the basic requirement for this request.
12-12-2006