|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 4
Sometimes this orderly arrangement does not work, usually when some JVM core code must dynamically load resources provided
by application developers. Take JNDI for instance: its guts are implemented by bootstrap classes in rt.jar (starting with J2SE 1.3), but these core JNDI classes may load JNDI providers implemented by independent vendors and potentially
deployed in the application's -classpath. This scenario calls for a parent classloader (the primordial one in this case) to load a class visible to one of its child
classloaders (the system one, for example). Normal J2SE delegation does not work, and the workaround is to make the core JNDI
classes use thread context loaders, thus effectively "tunneling" through the classloader hierarchy in the direction opposite
to the proper delegation.
By the way, the previous paragraph may have reminded you of something else: Java API for XML Parsing (JAXP). Yes, when JAXP was just a J2SE extension, the XML parser factories used the current classloader approach for bootstrapping parser implementations. When JAXP was made part of the J2SE 1.4 core, the classloading changed to use thread context classloaders, in complete analogy with JNDI (and confusing many programmers along the way). See what I mean by lack of guidance from Sun?
After this introduction, I have come to the crux of the matter: neither of the remaining two choices is the right one under
all circumstances. Some believe that thread context classloaders should become the new standard strategy. This, however, creates
a very messy classloading picture if various JVM threads communicate via shared data, unless all of them use the same context
loader instance. Furthermore, delegating to the current classloader is already a legacy rule in some existing situations like
class literals or explicit calls to Class.forName() (which is why, by the way, I recommend (again, see "Get a Load of That Name!") avoiding the one-argument version of this method). Even if you make an explicit effort to use only context loaders whenever
you can, there will always be some code not under your control that delegates to the current loader. This uncontrolled mixing
of delegation strategies sounds rather dangerous.
To make matters worse, certain application servers set context and current classloaders to different ClassLoader instances that have the same classpaths and yet are not related as a delegation parent and child. Take a second to think about why this is particularly horrendous. Remember that the classloader that loads and defines a
class is part of the internal JVM's ID for that class. If the current classloader loads a class X that subsequently executes, say, a JNDI lookup for some data of type Y, the context loader could load and define Y. This Y definition will differ from the one by the same name but seen by the current loader. Enter obscure class cast and loader
constraint violation exceptions.
This confusion will probably stay with Java for some time. Take any J2SE API with dynamic resource loading of any kind and try to guess which loading strategy it uses. Here is a sampling: