Thread context class loader...

Bryan Atsatt bryan.atsatt at ORACLE.COM
Mon Sep 17 19:55:40 PDT 2007

The OSGi RFP 83 [1][2] contains Thread context class loader requirements
that are clearly relevant to this JSR. Based on a great deal of painful
experience with the use/misuse of the thread context class loader, I
believe that 277 must address this issue to be successful :^).

I suspect that Thread.get/setContextClassLoader() will need to be
updated to use a policy based implementation.

At Oracle, in our EE system, we have no choice but to constantly switch
the TCL as threads are assigned to execute code from one of the many
possible concurrent applications. We tried various schemes for this,
with the most obvious being a special delegating loader assigned as the
TCL. But, due to JVM class caching, delegating loaders must have the
same lifecycle as those they delegate to, and this is tricky when your
threads are re-used for many different applications, each of which has
it's own lifecycle.

Our current solution overrides both the Thread
get/setContextClassLoader() methods, and uses internal server state to
determine which actual application loader to return. The state is reset
each time a request processing thread is returned to the pool
(Executor.afterExecute()) since application code often changes the TCL
(without the reset the thread pins the loader).

In an EE world, this approach works quite well since there is a natural
context for class resolution: the application. This large-grained
context is easily represented via a TCL, and that loader is then
unconstrained as to its visibility to other loaders. There is a clear
context switch opportunity as threads are assigned to execute
application code or returned to the pool.

In a purely module/bundle based environment there is also a natural
context: the module/bundle loader. But this is too fine-grained since
its expressed dependencies frequently won't (and shouldn't statically)
include SPI implementation classes specified by name. And there is no
switching boundary--each module/bundle loader must control it's own fate.

Clearly, one answer is to introduce some form of context which enables
the administrator/developer to broaden the search scope beyond the
module's natural dependencies. The Equinox "buddy" policy approach is a
good start, but probably needs some refinement/extension and new APIs.
For example, Thread get/setContextClassLoader() methods could delegate
to a policy object:

   interface ContextClassLoader {
       public ClassLoader get();
       public ClassLoader set(ClassLoader loader);

(or even a type that reexports the public methods of ClassLoader to
enable the policy to search across multiple loaders).

But we need to be very careful about the number and kind of policies we
support to minimize complexity in what is already an extremely complex
environment. Oracle's class loader framework has elaborate diagnostic
machinery built-in, which is called upon constantly to help solve
problems--there seems to be infinite ways to mis-configure a large
system of classes. And we *still* run across frameworks that don't even
use the TCL and so don't work properly in a multi-loader env.


The RFP also deals with serialization; I'll start another thread on that.

// Bryan

[1] EG Wiki:
[2] Public (requires registration):

More information about the jsr277-eg-observer mailing list