Any news on this one James ? Do you have any patch that could add jar:
support to SimpleClassLoader ? We could implement a workaround, but if
possible I would fix this by supporing jar URLs where not available.
Costin
On Fri, 7 Sep 2001, James THOMAS wrote:
>
> I'm using IBM's JDK 1.1.8
> I feel almost certain that it does not have a "jar" protocol handler.
>
> I tried your suggestion but I still get the exception:
> java.net.MalformedURLException: unknown protocol: jar
> at java.lang.Throwable.<init>(Throwable.java:74)
> at java.lang.Exception.<init>(Exception.java:38)
> at java.io.IOException.<init>(IOException.java:38)
> at
> java.net.MalformedURLException.<init>(MalformedURLException.java:38)
> at java.net.URL.<init>(URL.java:201)
> at java.net.URL.<init>(URL.java:222)
>
> Looking at JDK 1.1.8 javadoc it seems that a URL Handler for the protocol
> is created:
> "If this is the first URL object being created with the specified
> protocol, a stream protocol handler object, an instance of class
> URLStreamHandler, is created for that protocol:"
>
>
> James
>
>
> ==================================================================================
> ==================================================================================
>
>
> Thanks again James.
>
> I think I understand now.
>
> First question - what VM are you using ? JDK1.1.8 ( Sun and IBM ) seem to
> have handlers for jar protocol ( even if it's not standard AFAIK ). Long
> time ago I tested with kaffe and it worked - but I'm not sure I tested
> getResource().
>
> The real problem is not in DependClassLoader, but SimpleClassLoader, where
> getResource() is implemented. Even if we 'hack' DCL to not call
> getResource(), I think it would be better, as you sugest, to add code to
> support the jar protocol.
>
> The problem is in SCL.getResource(), the code is:
>
> // a jar:-URL *could* change even between minor releases, but
> // didn't between JVM's 1.1.6 and 1.3beta. Tested on JVM's from
> // IBM, Blackdown, Microsoft, Sun @ Windows and Sun @ Solaris
> if( r.zipEntry != null ) {
> try {
> return new URL("jar:file:" +
> r.repository.getPath() + "!/" +
> name);
> } catch(java.net.MalformedURLException badurl) {
> ....
>
>
> One thing you can try ( and may work ) is to replace this with
>
> new URL("jar", null, r.repository.getPath() + "!/" + name );
>
> This will avoid calling the handlers ( which are used to parse the local
> part ).
>
> I agree the right solution is to add the dummy handler ( or a 'real' jar
> handler ! ) in the compat package. It must at least parse the URL,
> otherwise it'll brake reloading ( since getFile() is used to add the jar
> location to the list of files that are checked for modifications ).
>
> Costin
>
>
>
> On Fri, 7 Sep 2001, James THOMAS wrote:
>
> >
> >
> > Thanks for the great info Costin.
> >
> > Just an FYI, I did implement another solution, which was to implement a
> > "Handler" class for the "jar" protocol. Interestingly enough, it was
> > sufficient to only have a class that is responsible for the "jar"
> protocol.
> > The implementation of the class could be crap because it is never used.
> > The explanation behind this is implementation of the DependClassLoader:
> >
> > Basic Algorithm of "loadClassInternal":
> > 1) If class is already loaded, return it.
> > 2) obtain the class as a resource from "parent" (but will don't construct
> > the "Class" yet). If the resource is not found, then throw a
> > ClassNotFoundException. This is where we are failing today because the
> > "jar" protocol does not have a handler in JDK 1.1
> > 3) load the class from "parent2" and return it if found.
> > 4) no create the class from the resource loaded in step 2
> >
> > By having a handler for the "jar" protocol, we get a non-null URL in step
> > 2, thus avoiding the ClassNotFoundException. And in my testing,
> "parent2"
> > was always able to load the class requested. Thus, the resource (i.e.
> URL)
> > obtained from step 2 was never used.
> >
> >
> >
> ===============================================================================
>
> >
> ===============================================================================
>
> >
> >
> > Thanks James, I'm very happy to see your contributions. ( and my
> > appologies for not testing with 1.1 often enough ).
> >
> > >
> >
>
>jakarta-tomcat-3.3-dev-src\src\share\org\apache\tomcat\util\depend\DependClassLoader.java
>
> >
> > > ======================================================================
> > > The method "loadClassInternal" appears to be incorrect. When loading a
> > > class, the code first retrieves the class as a resource from the
> "parent"
> > > class loader. But, the return value from the "getResource" is not used
> > > because the code then delegates the class loading to the "parent2"
> class
> > > loader ("parent2.loadClass(name)"). When running with JDK 1.1, the
> > > "getResource" returns null because the "jar" protocol is not valid (the
> > > exception message "unknown protocol: jar" is thrown from
> > SimpleClassLoader
> > > where a java.net.URL is constructed). This causes the
> > "loadClassInternal"
> > > method to throw a "ClassNotFoundException" prematurely because the
> class
> > > can successfully be loaded by one of the the parent class loaders.
> Below
> > I
> > > offer a solution but I think it would be best if someone with a more
> > > in-depth understanding of the code can validate this solution.
> >
> > The code is a bit tricky. 3.3 uses normal URLClassLoaders for loading,
> but
> > in order to support reloading we use an additional wrapper (
> > DependClassLoader ) that will collect dependencies ( since a servlet/jsp
> > can depend on multiple jars/classes ).
> >
> > For DCL, "parent" is the webapp class loader. "parent2" is the
> > applications class loader, parent of all webapp loaders.
> >
> > The code tries to make DependClassLoader as non-intrusive as possible (
> > i.e. the behavior of using DCL should be as close as possible to 'normal'
> > ).
> >
> > If a class can be loaded by parent2 ( the common app loader ), then we
> > just delegate to it ( that's the normal delegation that would be used if
> > no DCL was present ). We don't delegate to parent because then all
> classes
> > loaded as result of resolving the current class would not be registered
> as
> > depends ( parent will do all the loading without any notification ).
> >
> > If not, we'll use parent to get the bytes - then load them. The reason we
> > have DependClassLoader12 is to support the security context - I couldn't
> > find any other way ( like via jdkcompat ) since we need to call a
> > protected method in super.
> >
> >
> > > // check parent class
> > > if( parent != null ) {
> > > try {
> > > c = parent.loadClass( name );
> >
> > ^^^ That will not brake part of reloading - parent will load all classes
> > that are requested by the current class, and we'll not be able to record
> > that...
> >
> > I'll try to find another fix ( nice try ! :-).
> >
> > Costin
> >
> >
> >
> >
>
>
>