Hi folks,

I've been having a peek at the Tomcat main CVS branch in respect of its classloading 
behaviour.  Apologies if I have missed any discussion - I have only just subscribed, 
and I did not find much in the tomcat-dev archives a couple of days ago.

It appears to me that ClassLoading is not quite right in a couple of respects ( ie. 
not working 'as advertised' ), and if you're willing, I'd like to have a go at a 
couple of patches for it.

Here's the list of things that I consider to be broken, based on the understandings 
that: 


  A) the hierarchy should go: 

           SystemCL
              |                 <-- LAYER 1
          lib/common CL
           /     \              <-- LAYER 2
  lib/container lib/apps CL
                   |            <-- LAYER 3
                 WEB-INF/lib       << same CL, but with URLs
                 WEB-INF/classes      from both dirs, in this
                                      order...


  B)   a classloader which failed to find a class
       will delegate to it's parent a'la JDK 2 style,
       with the delegation behaviour in:
         JDK 1.2+ java.net.URLClassLoader
         JDK 1.1  org.apache.tomcat.util.compat.SimpleClassLoader



  List of broken behaviours:


  1)  LAYER 1 and LAYER 2 are broken ( do not delegate to parent )


     org.apache.tomcat.modules.config.ProfileLoader [ -r ]


     line 320:  commonLoader is set to be its own parent, if there
                was previously a commonLoader, or the System
                CL if not.


     line 331: ( same, with appLoader )


     line 343: ( same, with containerLoader )


     this is also a potential memory leak after a while,
     if initClassLoaders() is called more than once.




  2) LAYER 3 bypasses straight to the System CL: 
 
     there is a piece of code in 

      org.apache.tomcat.modules.config.LoaderInterceptor11 [

     ( line 197 - 207 )

     
         if( useAL && !context.isTrusted() ) {
           if( debug > 0 ) log( "Using webapp loader " + context.isTrusted());
           parent=cm.getParentLoader();
         } else if( useNoParent ) {
           if( debug > 0 ) log( "Using no parent loader ");
           parent=null;
         } else {
           if( debug > 0 ) log( "Using container loader ");
           parent=this.getClass().getClassLoader();
         }


     I am not really sure why this piece of code is as it is.

     note:  

     - useAL is set by setUseApplicationLoader( boolean ).  
       I could find no callers of this method in the source,
       but the method is still public.

     - same story for useNoParent, which is set by
       setUseNoParent( boolean )

     - since useAL is initialised in the constructor
       to false, it would appear that if(1) is never called.

     - since useNoParent also defaults to false, it
       would appear that if(2) is never called

     - so it must always default to if(3), and this line
       does NOT gurarantee delegation to the 
       container loader!  ( expected 

         Context.getContextManager().getContainerLoader()

       instead )

       


  3) Inconsistent directory-scanning behaviours

     org.apache.tomcat.modules.config.ProfileLoader [ -r ]

         makes use of IntrospectionUtils, but 

     orb.apache.tomcat.core.LoaderInterceptor11  [ -r ]

         does not ... 


     as a result of this, there are different behaviours
     in classloading with respect to the recursion of
     directories.


     

Here's a list of questions I need answered to make some improvements:

 0) Are there good historical reasons why the above behaviours are as they are?


 1) is it OK to not use the IntrospectionUtils when constructing classpaths?  I find 
its API a little awkward.  ( Would factor out classpath-ish utilities into their own 
Class, deprecate existing classpath-ish methods on IntrospectionUtils  ).

 1b) assuming yes, what package should that class be placed into?



 2) is it OK to introduce the following new behaviour that allows the user to specify 
order in directories where classloading occurs?

    IF there is a file called 'classpath.properties' ( call it what you like ), in the 
root directory of a classpath location, or in any of its descended directories,

    AND that file contains a line 
'org.apache.tomcat.classpath.order=<comma_separated_list_of_files>'

    THAT for each item in <comma_separated_list_of_files> which is actually an 
immediate child of the directory according to the filesystem, it is placed into the 
classpath in that particular order.  Unorded entries would be appended to to the end 
of the list for that directory.

    [ I already have an implementation of this if anyone wants to see it first.  Also, 
I am prepared to writup the user-documentation before actually doing it. ]



 3) where is the appropriate place to put user-documentation about classloading 
behaviour?


 4) is there a test ( eg. JUnit test? ) or test-suite ( eg. WatchDog? ) or test 
web-app, that verifies contracts about classloading behaviour with respect to the 
Servlet 2.2 specification?



regards,
David.


----
David Bullock - http://www.lisasoft.com/

Sun Certified Programmer for Java 2 


"The key ingredients of success are a crystal-clear goal, a realistic attack plan to 
achieve that goal, and consistent, daily action to reach that goal."

Steve Maguire, "Debugging the Development Process". 

Reply via email to