tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ed Korthof ...@apache.org>
Subject classloader issues (ClassCastException on org.xml.sax.Parser)
Date Tue, 22 Jan 2002 20:49:13 GMT
Hi --

At my company, we've been using tomcat out of cvs for our development.
(We'll be releasing software which uses Tomcat 4.0 rather than
Apache-JServ shortly.)  During the last update which we did, we found
our XML-RPC service stopped working -- it started giving us
ClassCastExceptions.  Eventually, we traced it down to classloading
issues which were introduced in 1.30 of WebappClassLoader.java :


----------------------------
revision 1.30
date: 2002/01/03 16:36:09;  author: remm;  state: Exp;  lines: +88 -11

- Adds some filtering on the JARs, similar to what is done by the
  ClassLoaderFactory.  That should prevent overriding classes which
  shouldn't be overridden (and which is actually a spec requirement).
  For example, it is now possible to actually run JSPs even with an old
  servlet.jar in the /WEB-INF/lib directory.
- I think this patch should be ported to the 4.0.x branch, since it
  prevents lots of user errors.
----------------------------

(reformatting done so this will be clean in < 80 columns).

Anyway -- here's the way our problem works.  We have xml-rpc.jar in the
webapp classloader.  xml-rpc.jar needs an xml parser -- and we were
using xercex.jar for that.  However, xerces.jar has the
javax.xml.parsers.DocumentBuilder class in it -- which means that the
webapp classloader *silently* (a loud warning would be appropriate even
when debugging is off) ignores that class.

xml-rpc.jar has org.xml.sax.Parser in it -- so when classname resolution
is done for xml-rpc, it finds Parser in the WebappClassLoader.  However,
when xml-rpc looks for its XML parser, it finds xerces -- and now xerces
isn't defined in the webapp classloader, it's defined in the next level
up (the shared classloader, I believe).  That would work fine -- except
that when xerces resolve org.xml.sax.Parser, it cannot find the version
which is in the WebappClassloader -- it can only find the version which
is in the shared classloader (it's in xerces.jar).  Two classes differ
if their classloader differs, so a ClassCastException is the correct
error.

AFAICT our solutions are:
1) use a different XML parser (and ensure it doesn't have
   org.xml.parsers.DocumentBuilder in it -- which is fine only unless
   WebappClassLoader is not changed to forbid other classes which 
   XML parsers are likely to include with them)
2) move xml-rpc.jar entirely out of the WebappClassloader and put it
   in the shared class loader (this would require that we move
   everything which uses an XML parser into the shared classpath --
   definitely not ideal)
3) remove org.xml.parser.DocumentBuilder from xerces.jar (similar to #1,
   but we know in advance that we have to muck with the .jar file in
   a problematic way).
4) toggle the behavior of the WebappClassloader in server.xml by
   telling it 'delegate="true"', so it delegates to its parent first.
   
The last one of these seems to work fine for us -- and it does actually
seems like a reasonable approach.  But it won't be available to at least
some people (why else would you attempt to allow users to override
classes in the webapp classloader?) ...

I think the fundamental problem is a bad specification (allowing people
to override some classes in a child classloader -- and trying to prevent
them from loading others -- is just silly); but it could be improved in
tomcat in a couple of ways.  I haven't yet tested this, but I think you
would have *far* better protection from bad .jar files if you moved
those security checks (which are currently used to disable .jar files
entirely -- IMO, that's wrong) into loadClass -- and change them so that
they check the class name against a list of packages, rather than just
looking for a few specific packages.

That would avoid encouraging stupid user tricks (#3 up above) and
actually be rather reliable, in terms of catching classes which
shouldn't be redefined in the child classloader.  It would also have
avoided the ClassCastException which we were seeing.

Failing that -- at least tomcat should do more in the way of logging
it if it decides not to accept a given .jar file because of the classes
the .jar file contains ... and this feature should be documented in
either case.

I'm happy to provide patches for consideration (as soon as I can get a
tomcat dev environment set up -- but I think I can get some help from
some folks at CollabNet who have build environments set up).

thanks --

Ed



--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>


Mime
View raw message