JDK-4219095 : inheritable thread locals: need way to snapshot and recreate complete state
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.2.0,1.3.1
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: solaris_2.5,windows_2000
  • CPU: x86,sparc
  • Submitted: 1999-03-10
  • Updated: 2003-06-23
  • Resolved: 2003-06-23
Related Reports
Relates :  
Relates :  
Description
There should be an API for taking a complete snapshot of the current state of all of the inheritable thread local variables in the current thread and for restoring the current thread's inheritable thread local variables to the values stored in such a snapshot.  The semantics of a combination of the snapshot and restore operations on a complete set of inheritable thread local variables should probably be the same as when such thread local variables are inherited by the newly-created child thread (i.e. calling childValue(), etc.).  The execution of at least the restore operation, if not the snapshot operation as well, should probably require a specific (new) runtime permission.

This functionality is important for system libraries that invoke callbacks into application-level code, especially as the use of inheritable thread local variables becomes more common.  Oftentimes, a system library will lazily create the threads that it will use to invoke callbacks the first time such a callback is registered.  In the interest of performance and scalability, the library will pool and reuse those threads to invoke callbacks to other application-level code that is completely unrelated to the first component that registered a callback with the library, yet all of the callbacks invoked in the reused thread will have the inheritable thread local variables set to the values that were inherited from when the thread was created in the context of the first client of the library.  This behavior seems wrong and surprisingly unpredictable, it causes the library to expose a global state that it was not intending to expose, and depending on the use of the affected inheritable thread local variables, it could represent a security hole.

With RMI, for example, if a certain context-specific inheritable thread local variable Foo is set to X when the first remote object happens to be exported on a particular port in a given VM instance, currently, whenever the code for *any* remote method received on that port for any, potentially unrelated remote object is executed, Foo will still have the value X.  Depending on the meaning of Foo, this behavior could have surprising results and cause non-deterministic bugs.

Say that Foo is being used to represent the identity, for authorization purposes, that the code in the current thread (that is exporting the first remote object) is executing as: all future remote methods will execute in a thread with the same identity.  The Java Authentication and Authorization Service documentation describes how it uses java.lang.InheritableThreadLocal in this sort of way:

http://javaweb.eng.sun.com/~charlie/jaas/javax/security/auth/Subject.html

Without such an API as requested by this RFE, there is nothing that a system library like RMI can do to control the values of inheritable thread local variables that it does not know about (to preserve them appropriately on behalf of each client's application context).  Note that the desired behavior could be effected by simply using thread creation to preserve inheritable thread local state: RMI could create a new pool of threads for every single remote object exported and only dispatch remote methods to a given remote object using threads in the pool for that particular object, but few would argue that in practice, RMI should be constrained to such a wasteful threading model.

RMI makes the explicit effort to preserve the "access control context" and the "context class loader" from when a remote object was exported to when one of its remote methods is executed.  The current access control context can be viewed as a special kind of thread local variable that is stack-scoped, and the context class loader is basically an inherited thread local as well-- it is a field of java.lang.Thread that is inherited by child threads-- but it isn't based on the java.lang.InheritableThreadLocal framework (for whatever reason).  RMI goes through the necessary explicit effort of preserving these properties of thread context from remote export to invocation because it knows about them, but it is quite conceivable that there could be other such properties that deserve similar treatment that RMI doesn't know about.  If other such properties are implemented using java.lang.InheritableThreadLocal, RMI should be able to save and restore them as appropriate without compromising or constraining its threading model.

Comments
WORK AROUND A snapshot of the complete state of the current thread's inheritable thread local variables can be taken by spawning a child thread, and future code can be executed in the preserved inheritable thread local state of that snapshot by executing code in threads further spawned by that child thread. This demonstrates that the requested functionality would not allow behavior that is not currently possible, but in most cases it does not represent a viable solution in practice, due to performance and scalability concerns.
11-06-2004

EVALUATION This controversial request has been discussed many times over the years. Threadpools and other callback frameworks are open to isolation problems involving ThreadLocals and InheritableThreadLocals. Nobody has yet shown that these are likely to be frequent in nature or to be specially malign. Several proposals have been made to correct these problems, but the proposals raise new issues, including different isolation problems, code breakage, and (potentially) memory leaks or crashes. Nobody has shown those problems to be likely in nature either. The proposals that attempt to fix isolation problems for callback frameworks do so by overriding primitive language semantics, and thus add a layer of complexity the impact of which is difficult to anticipate fully. On the balance we do not see a clear benefit in the proposals. These issues were again discussed, this time by by the JSR-166 expert group and "observing community." Again the conclusion was that things should be left as they are. ###@###.### 2003-06-23
23-06-2003