ThreadContextClassLoader

From APIDesign

Revision as of 19:33, 7 November 2010 by JaroslavTulach (Talk | contribs)
Jump to: navigation, search

Java provides way to associate a special class loader with each of executing threads. This is handy, as often the executing class needs access to more than classes visible by its own classloader. However it is also accompanied with problems. Especially in modular systems. When it is not easy to control thread management (e.g. application can create and destroy threads on the fly), it is hard to make sure the ThreadContextClassLoader is specified properly.

Things get even more complicated as each modular runtime container may have different idea what ThreadContextClassLoader shall do. I know what I am talking about, I have spend last month trying to reimplement Netbinox OSGi container to provide ThreadContextClassLoader which is friendly to NetBeans modules as well as bundles comming from Equinox world.

The need for enhanced ThreadContextClassLoader is clear as can be seen summary about Equinox class loader enhancements. It summarizes the need as well as the solution taken by Equinox guys. Everything is built around buddies - e.g. each module can define its own buddy loading policy and let others to register is buddies.

The NetBeans ways is slightly different. It knows packages of all enabled modules and the ThreadContextClassLoader can load any classes from any of their packages (even non-public, e.g. not exported). It is build around observation that it does not make much sense in a running application to have the same implementation module loaded twice.

Both of the Worlds?

It is easy to create a union behavior that will support both ways. And I did it quite easily. If the class is not found the NetBeans way, then Netbinox tries the classical Equinox way. This guarantees that if the class is present in the system and either belongs to enabled module or it is accessible via buddy policy, it will be loaded.

Everything looked fine, until I started to execute existing tests in this new system. The testing framework (built around JUnit just like NetBeans NbJUnit), has the classes visible twice. Once on application classpath and once in the available bundles. I claimed that I can successfully find a class, if it can be found just a paragraph ago. Yes, I can, but I cannot guarantee it will be the right one. The problem is NetBeans ThreadContextClassLoader by default delegate to parent classloader first (e.g. the class is usually loaded from the application classpath), while the Equinox ThreadContextClassLoader prefers the bundle version.

When there are two version of a class visible (like in case of unit testing), having best of both worlds is a way to hell. It leads to randomness and bunch of ClassCastExceptions.

The NbJUnit ClassLoader

TBD

Personal tools
buy