cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Craig R. McClanahan" <Craig.McClana...@eng.sun.com>
Subject Re: re loading of classes in tomcat 3.2b4 is _sloooooow_@6
Date Tue, 26 Sep 2000 19:42:36 GMT
Niclas Hedhman wrote:

> "Craig R. McClanahan" wrote:
>
> > The current Catalina classloading strategy is to create the following kinds of
> > classloaders at startup time:
> >
> > * The JVM (at least the Sun one) itself sets up the bootstrap
> >   class loader with the contents of $JAVA_HOME/jre/lib/ext
> >   (the system extensions you have installed) plus its own
> >   basic runtime classes.
>
> Not exactly.
> The Bootstrap classloader is only responsible to deliver the
> $JAVA_HOME/jre/lib/rt.jar classes. The JVM will then instantiate a URLClassloader
> for the $JAVA_HOME/jre/lib/ext directory (and directories found in one of the
> system properties (java.lib.ext?), formally called the Extension classloader,
> using the Bootstrap CL as the parent.
> The startup is then creating the System CL with the Extension CL as the parent,
> which points to the classes in the -cp and CLASSPATH settings.
>

True.

Classloaders are rather arcane, and I skipped over a few details.

>
> > * The system class loader is configured to contain the
> >   $CATALINA_HOME/bin/bootstrap.jar file, plus all the
> >   jars in $CATALINA_HOME/lib.  Any CLASSPATH
> >   variable that the user currently has set is totally
> >   ignored (I'm negotiable on this, but I'm really tired of all
> >   the user problems related to class paths).  The JAR files
> >   here should be the ones required by more than one webapp.
> >   The parent of this class loader is the bootstrap class loader.
>
> Is this the standard system CL or a home brew?? If standard, how do you manage to
> kill the CLASSPATH inclusion?
>

It is now based on URLClassLoader, but adds features required to support auto-reload
when class files are changed.

Arg, I see that I typed this wrong ... the parentage tree of a webapp classloader
actually ends up looking like this:

    Bootstrap
        |
    System Extensions
        |
    System Classloader (bootstrap.jar + $CATALINA_HOME/lib)
        |
    Webapp Classloader

The parentage tree for the internal Catalina classes are slightly different:

    Bootstrap
        |
    System Extensions
        |
    System Classloader (bootstrap.jar + $CATALINA_HOME/lib)
        |
    Catalina Classloader ($CATALINA_HOME/server)

The Catalina classloader is an implementation of the same class used for webapps
(org.apache.catalina.loader.StandardClassLoader) but the set of repositories is
configured dynamically from the $CATALINA_HOME/server directory.

When webapp classloaders are created, the parent classloader is explicitly set to be
the system classloader so that the Catalina classes get bypassed.  This is one of the
protections against malicious webapps being able to munge around with Catalina
internals by casting the request and response objects they receive back to the
internal implementation classes.


>
> > * The Catalina class loader contains all of the implementation
> >   classes of Catalina itself, and libraries it needs.  This is created
> >   automatically from the jar files in $CATALINA_HOME/server.
> >   These classes are *not* exposed to webapps.
>
> Why would there be a need for a separate "Application" classloader? That would
> typically be the purpose of the System CL. Or is it that the "Catalina CL" uses
> the Extension CL as the parent, bypassing the normal System CL, and provides the
> same functionality, and thereby easily bypasses the CLASSPATH settings? But the
> statement below indicates that this CL is a sibling of the WebApp CLs.
>

Each webapp has access to a unique set of classes -- the ones in WEB-INF/classes/ and
WEB-INF/lib/*.jars.  Therefore they need separate classloaders.

The webapp CLs are siblings of each other, but the parent CL in each case is the
System CL, not the Catalina one -- because they are created with an explicit parent.


>
> > * The webapp class loader (one per webapp) is configured from
> >   the WEB-INF/classes and WEB-INF/lib/*.jar contents of this
> >   webapp.  It's parent class loader is the system class loader
> >   (see above).
>
> > One of the big issues with any sort of "shared library" approach is, what do
> > you do when the same class appears in both the webapp class loader and the
> > system class loader?  Which one wins?
> >
> > In Tomcat 3.x (<= 3.2 at least), the webapp classloader follows the standard
> > Java2 delegation model, and always goes to the parent first (i.e. the system
> > classpath), and then in the webapp.  If you've got the same class both places
> > (like an XML parser or a JDBC driver), the one on the system classpath wins.
> > By the way, this is what caused so much grief in Tomcat 3.1 with people trying
> > to run their own parsers that had some classes in common with the "xml.jar"
> > parser shipped with 3.1.
> >
> > In Tomcat 4.0, Catalina by default follows the new search order articulated as
> > a "recommendation" in the servlet 2.3 draft spec:
> > * WEB-INF/classes
> > * WEB-INF/lib/*.jar
> > * System class loader
> > so that a library found in the webapp will always win.  This can be configured
> > out (although not very gracefully at the moment), but seems to meet the
> > majority of use cases better than the previous scheme.
>
> This sounds like a security hole... I can not pinpoint a possible attack, but one
> of the reasons for the Java2 model was security.
>

There are multiple levels to the issue of security.  Let's look at a couple of them:

* Who can install webapps in your server in the first place?  Normally, this is done
  by a system administrator who makes some sort of "trust" decision.

* What bad things can a webapp do (let's assume it's a third party closed source
  product that you cannot examine)?  If the webapp has write access to
WEB-INF/classes
  or WEB-INF/lib, it can pretty easily import new classes (say, from the network)
  and install them.  That's why you would normally want to run a security-sensitive
  app under a Java security manager as well (not yet supported by Tomcat 4.0, but
  it will be) to prevent such things.

* Can a webapp mess around with internal server objects?  No -- not only is the
  Catalina CL skipped when setting up the webapp CL, the webapp CLs are also
  configured to refuse any attempt to load a class named "org.apache.catalina.*",
  and to delegate upwards unconditionally for any class that starts "java.*" or
  "javax.servlet.*".  So, a webapp cannot impersonate a system class either.

All of the security related stuff is going to be summarized into a document that
contains assertions about what Catalina does and does not allow, with pointers to the
implementation of the various protections.  Given that, we will be able to audit the
robustness of the security features in place and fix any flaws that are found.

>
> > > > So the first question would be : when an application share common library
> > > > (say DOM and sax packages), what are the benefits of delivering the war
> > > > Webapp file with the web-inf/lib conataining the duplicated library (for
> > > > cocoon the shared libraries are Xerces (since catalina can works with
> > > > it), tools.jar (which is 4mg big!), jndi.jar, etc ...)
> > >
> > > The first and basic advantage is ease of installation. Drag your war
> > > file and you're done.
> > >
> > > The second advantage is complete separation: no problem with class cast
> > > exceptions and all that since the web-inf/lib takes precedence (I like
> > > this very much)
> > >
> >
> > The third advantage is that some libraries will not work correctly unless they
> > are installed in the webapp.  I believe Cocoon has run into this -- I'll
> > describe what I ran into with Struts because it's similar.
> >
> > Struts includes a module called Digester (very similar to the XmlMapper that is
> > used inside Tomcat to configure itself from the server.xml and web.xml files).
> > One of the things you can do is create a new object when a particular XML
> > element is encountered.  But, if the digester classes are loaded from the
> > system class path, and the Java class of the object you're trying to create is
> > in the webapp (a very typical case), you're out of luck --
> > ClassNotFoundException because the Digester tries to use the classloader it was
> > itself loaded from (i.e. system class loader).
>
> That is because of inappropriate use of dynamic classloading. The procedure is to
> properly set up the thread's context classloader, and all dynamic classloading
> should use Thread.currentThread().getContextClassloader().loadClass() to get
> around this problem.
>

This works only in Java2 -- JDK 1.1 does not have the concept of a context class
loader, so you cannot use it if your app has to remain compatible with 1.1.

>
> However, I agree that shared libraries are badly defined in the W3C/XML world.
> a) The classes from W3C were never properly packaged and maintained into JAR
> files. Every user tend to put them into their own JARs
> b) The same classes are not compatible between versions. I can not simply replace
> them with the latest version (by compiling and putting them in a JAR in the
> lib/ext/ directory) which would temporarily solve my problems.
>
> But I guess you are on top of this...

I wouldn't say necessarily "on top of" -- more "suffering the consequences of" along
with everyone else :-).

>
> Niclas
>

Craig

====================
See you at ApacheCon Europe <http://www.apachecon.com>!
Session VS01 (23-Oct 13h00-17h00):  Sun Technical Briefing
Session T06  (24-Oct 14h00-15h00):  Migrating Apache JServ
                                    Applications to Tomcat



Mime
View raw message