On Mon, 2005-02-14 at 12:14, Ceki G�lc� wrote:
> Robert,
> 
> I am a bit surprised by your question.

i needed to make sure that i hadn't misunderstood what you were trying
to say...

>  As the current release manager
> for JCL, I suppose that you are aware that LogFactoryImpl only uses
> the thread context class loader (TCCL) to search for classes. You were
> aware of that, weren't you?  

of course

> In theory, this is supposed to let a copy
> of commons-logging.jar placed in a parent class loader to discover
> another logging API, say log4j, whose classes are visible to a child
> class loader with the child loader also set to be the TCCL. 

that's untrue and a little misleading: 

the reason why those who wrote the classloading code relied on the
context classloader is that this is the classloader that should be used
by well behaved components running in J2EE containers. this is what
correct isolation in a container environment means.

there are many consequences which spring from this design decision. some
of these are a little unfortunate.

i think i agree with richard that a more pragmatic (rather than
dogmatic) approach would be wiser. it would better to ensure that the
configuration was appropriately isolated and then load a compatible
class which satisfies the configuration. i suppose some thought would
need to be put into whether there are any realistic security
implementations if this approach were adopted. 

> However,
> this dynamic discovery does not work. The copy of log4j.jar must be
> placed next to commons-logging.jar.  

this is a basic feature of delegating classloaders. (i even looked this
one up to make sure my memory wasn't playing any tricks:
http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html#72007)

for example, suppose class Alpha is linked to class Beta which is linked
to class Gamma, that classloader C is a child of classloader P, that C
defines Alpha and Gamma and P Beta but not Gamma or Alpha. 

(apologies that my diagrams aren't up to richard's standards) 

Classloader      Defines
-----------      -------
    P            Beta
    ^
    |
    C            Alpha     Gamma 


Links
-----
Alpha -> Beta -> Gamma

now consider what happens what Alpha is loaded by C. C defines Alpha
which is linked to Beta. therefore C is used to load Beta. C delegates
to P which defines Beta. Beta links to Gamma. P defines Beta and is
therefore used to load Gamma. However, P cannot load Gamma and so
everything blows up.

a practical example occurs when jars containing Alpha and Gamma is
placed as a utility library in an EJB container and a jar containing
Beta is placed in the container base loader.

the usual rule (when delegating classloaders are involved) is that any
dependencies need to be placed together or higher in the classloader
hierarchy. since commons-logging-api by default has a runtime dependency
upon commons-logging and commons-logging (a slightly fuzzy one) upon
log4j when commons-logging-api is placed in the root classloader, so
must the other jars. 

this would be equally true for a static arrangement (UGLI say). all
dependent jars would need to be placed together or higher in the
hierarchy.

so, i'm not sure how this pertains to the static-verses-dynamic debate.

IMHO, from a practical perspective having to ensure that libraries are
in the right places comes with the territory: it's something that anyone
involved with deployer J2EE applications gets used to doing. 

> Moreover, the copy of
> commons-logging.jar must be placed very high in the class loader tree,
> say in the system class loader or the application server's class
> loader, but that is not all. There must not be other copies of
> commons-logging.jar in war files of web-apps.

i'm not sure how true that is. the stock advice arises from the fact
that JCL is used very widely and has a habit of turning up unexpected
high in classloader hierarchy. 

> To cut a long story short, do to anything meaningful reliably, JCL is
> a lot more complicated to set and even when set up "correctly" brings
> no benefits when compared to static API binding as found in UGLI.

there are several use cases when static binding is admittedly superior.
(for those i would prefer byte code engineering over multiple
distributions since it allows selective doping of particular components
but let's keep focused on compile time solutions).  

however, the price of deploying a statically bound API high in the
hierarchy (where JCL is expected to be able to function) is that
applications can no longer be configured in isolation. so, there is
price to pay. 

> I urge you run though the examples in [1] which should demonstrate to
> you how badly and irreparably JCL is broken. The source code is all
> there. Even if you don't trust my opinion, 

i'm very reluctant to take anyone's opinion on trust when it comes to
JCL. the gestation of JCL was very difficult and the classloading code
was developed over a period by senior tomcat folks. JCL also has a huge
user base. in practical terms, it's successful but limited.

> at least trust your java
> compiler and your JVM.

but it's not the code that's the issue. i just don't understand what the
issue is that provokes such a strong reaction from you. 

the api/implementation separation doesn't work very well. this is a
known issue and if this turns out to be at the root of your complaint
then you'd have a point. 

there is actually one thing i discovered about the LogFactory that i
didn't expect (but i wanted to reply before). it's better coded than i
thought it was which leads me to wonder why it doesn't work better. but
i wanted to finish this email before investigating... 

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to