Return-Path: Delivered-To: apmail-jakarta-tomcat-user-archive@jakarta.apache.org Received: (qmail 97064 invoked by uid 500); 26 Jul 2001 16:15:13 -0000 Mailing-List: contact tomcat-user-help@jakarta.apache.org; run by ezmlm Precedence: bulk Reply-To: tomcat-user@jakarta.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list tomcat-user@jakarta.apache.org Received: (qmail 97043 invoked from network); 26 Jul 2001 16:15:13 -0000 Received: from msgrouter1.onetel.net.uk (mirapoint@212.67.96.140) by h31.sny.collab.net with SMTP; 26 Jul 2001 16:15:13 -0000 Received: from octovma (host213-120-114-227.in-addr.btopenworld.com [213.120.114.227]) by msgrouter1.onetel.net.uk (Mirapoint) with ESMTP id ADM50968 (AUTH vmassol); Thu, 26 Jul 2001 17:15:14 +0100 (BST) Message-ID: <020301c115ee$55e81f40$e37278d5@vizzavi.fr.corp.vizzavi.net> Reply-To: "Vincent Massol" From: "Vincent Massol" To: References: <022201c1150f$ac075920$e37278d5@vizzavi.fr.corp.vizzavi.net> <3B5EDB60.76E03009@tid.es> Subject: Re: WebappClassLoader question Date: Thu, 26 Jul 2001 17:16:24 +0100 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2479.0006 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2479.0006 X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N Thanks Alex, I don't think the standard classloader mechanism is involved here. I believe it is a 'feature' of Tomcat and more specifically of it's WebappClassLoader. When you do standard java code and you have the following situation : 1st -> 2nd --- (using reflection) --> 3rd (not in classpath) then the error always happen in the 2nd class and you can put the code between a try catch block and you'll be able to catch the ClassNotFoundException. However what happens here is that the error happens when calling a method on the 1st class that instanciates the 2nd class ! This is what I don't understand. Am I dreaming or is this a behaviour of Tomcat 4 ? Thanks -Vincent ----- Original Message ----- From: "Alex Fern�ndez" To: Sent: Wednesday, July 25, 2001 3:44 PM Subject: Re: WebappClassLoader question > Hi Vincent! > > I've run into the same situation a couple of times, when one class uses > a second class, and this second class uses a third one that is not > present. > > 1st -> 2nd -> 3rd (missing) > > One would think that instantiating the 2nd should give an error, but > that loading the 2nd and/or instantiating the 1st should be ok. In fact, > all of the behaviors raise exceptions. > > The following paragraph in ClassLoader javadoc might be of help: > > "The methods and constructors of objects created by a class loader may > reference other classes. To determine the class(es) referred to, the > Java virtual machine calls the loadClass method of the class loader that > originally created the class." > > Or, to find out what the JVM is doing, the spec is here: > http://java.sun.com/docs/books/vmspec/ > > Hope it helps. > > Un saludo, > > Alex. > > > Vincent Massol wrote: > > > > Hi, > > > > Here is the situation : > > > > * I have a class that makes use of JUnit (by extending the JUnit > > TestCase class). Let's call it ServletTestCase > > * I have a second class that is used to call a method in > > ServletTestCase, let's call it MyProxyClass > > * I have a third class (a servlet) that does _not_ make use of JUnit. > > Let's call it ServletTestRedirector. This class actually instanciate > > MyProxyClass and calls one of its method. > > * I package these classes in a war file and I _don't_ include > > junit.jar in this war file > > > > When I access the servlet, I get a ClassNotFoundException on a JUnit > > class. So far it is normal ... > > When I debugged it, I have actually found that the error was happening > > when ServletTestRedirector was instancianting MyProxyClass (which does > > _not_ make use of JUnit) and before it was calling its method. > > > > Here is the stack trace I got : > > > > java.lang.NoClassDefFoundError: junit/framework/TestCase > > at java.lang.ClassLoader.defineClass0(Native Method) > > at java.lang.ClassLoader.defineClass(ClassLoader.java:486) > > at > > java.security.SecureClassLoader.defineClass(SecureClassLoader.java:111) > > at > > org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLo ader.java:1475) > > at > > org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.jav a:836) > > at > > org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav a:1215) > > at > > org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav a:1098) > > at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313) > > at > > org.apache.commons.cactus.server.ServletTestRedirector.doPost(ServletTestRed irector.java:143) > > Here is what I imagined is happening (tell me if this correct or wrong > > !) : > > > > As MyProxyClass is within the war file, the WebappClassLoader gets > > called to load it. The WebappClassLoader, in trying to find out the > > correct class, actually loads some other class in memory, and thus the > > ServletTestCase, which fails to load because the junit jar is not in > > the classpath. > > > > Is that correct ? > > Don't you find it strange that the error about the missing class is > > reported when calling a class that has nothing to do with the problem > > ? It gets very hard to catch errors ... > > > > For example, in MyProxyClass, the code that calls the ServletTestCase > > method is as follows : > > > > ServletTestCase testInstance = null; > > try { > > testClass = Class.forName(theClassName); > > Constructor constructor = testClass.getConstructor(new > > Class[] { String.class }); > > testInstance = > > (ServletTestCase)constructor.newInstance(new Object[] { theMethod }); > > } catch (Exception e) { > > logger.debug("Error instanciating class [" + theClassName > > + "]", e); > > e.printStackTrace(); > > throw new ServletException("Error instanciating class [" + > > theClassName + "]", e); > > } > > And there is never any exception caught here .... because the error > > happens earlier in the call stack, when the ServletTestRedirector > > instanciates MyProxyClass ... > > > > ... or am I missing something ? :) > > > > Thanks > > -Vincent Massol > > >