Well, it seems that the shared classes in shared\lib really are responsible for this. I tried to move those in the WEB-INF\lib directories. There are a couple of new problems to work out, nothing serious, but the problem with the "shared" classes vanished.
Thanks again for your assistance. > did lose my mind in the maze of classloading several time. I know what you mean :o) Sascha > -----Original Message----- > From: delbd [mailto:[EMAIL PROTECTED] > Sent: Thursday, June 02, 2005 4:02 PM > To: Tomcat Users List > Subject: Re: WebappClassLoader - don't understand what's happening > > Le Jeudi 2 Juin 2005 14:50, Herrmann, Sascha (GE Healthcare) a écrit : > > > Any library having static methods like > SomeLibraryClass.setXYZ(xyz); > > > SomeLibraryClass.getXYZ(xyz); > > > > Wow, wow, wow .... . You mean any class that has static > methods gets > > shared?? Any class that calls static methods? Could you > explain that a > > bit further, please? > > > > No, i mean a shared class which has static methods could > potentially serves as a bridge for objects between web > applications :) I forgot the 'shared' in the sentence 'Any > shared library having static methods', sorry ;) > > > > so i doubt usefull informations comes from it. > > > > It works for all the other methods I put this code in. It > seems that > > Tomcat assigns the CL to thread when it's fetched from the pool. > > Possible, might have a sense in terms of security. > > > > > It's definitely the case. We have a static log variable in the > > classes. It holds the log4j logger reference. All the debug output > > from the class goes into the log file of the application > that started > > first (the one that loaded the class). Even the output when > I use the > > app that was started second. That's how I noticed in the > first place. > > > > is log4j a shared lib? if this is the case, might explain why > all logs are in one common file (see log4j explanations for > details, it's stated log4j should be put in WEB-INF/lib and > nowhere else to prevent problems in J2EE environnement). In > your case, this simply mean the config is shared, like is the > log4j libraries. > Don't mis this point: static Logger > Logger.getLogger(SomeClass.class), does not mean the logger > is 'the one for the class' but this mean the Logger is 'the > one having the name some.package.SomeClass' this difference > is subtle but has lots of implications when several different > classes with excaclty the same name and package are using a > common Log4j library. > > > Are you familiar with the classloading stuff? > > > > did lose my mind in the maze of classloading several time. > > > I was wondering ... when the WebappClassLoader doesn't find > the class > > in its path, and then delegates the loading to the shared > classloader > > ... and when then the shared classloader loads the class .... who > > resolves the dependecies of this loaded class? Does the > > WebappClassLoader get a shot first, or is it still the > shared classloader? > > when the shared class loader loads a class in the delegation > model, it assigns itself to the class.getClassLoader(). That > is any other class further loaded by object of the first > class will be loaded using the shared classloader. > This is the excpected behaviour. So in your question, the > answer is "no the WebappClassLoader is not given a chance to > resolve as shared classloader does not know it's childrens" > > > > > What if the shared classloader loads a class, and then > cannot resolve > > a referenced class (because it's in one of the app's WEB-INF\lib > > directories) > > the sharedclassloader is unable to load anything in > WEB-INF/lib, because it doesn't know about it. > So in your case, it will ask it's parent (probably the JVM > classLoader) which will throw a ClassNotFoundException > > > > ... how does he determine which child WebappClassLoader he > is to use? > > And who is registered in the JVM then as initiating classloader? > > The delegation model goes down - top (from the calling class' > classloader to the root classloader), it nevers goes back > down later. A class instanciated by the shared classloader, > is *never* able to load any class from a WEB-INF/lib using > Class.forName() > > > > > I am asking because we have classes in our shared\lib > directory. Those > > classes use a factory pattern to instantiate classes (that > can be in > > the WEB-INF\lib dirs). Now, I wonder how these classes are loaded, > > that the factory class in shared\lib needs? > > Sorry but if factories are in shared/lib, they are unable to > load anything from WEB-INF/lib .... with one exception, if > they are passed as argument the classloader of the > WEB-INF/lib to use, they can use it to instanciate the class. > But this is not a suggested way to write factories. > However, a better behaviour would anyway be to put those > factories in WEB-INF/lib insteed of shared/lib > > > > > Or am I thinking in the wrong direction? Does the WebappClassLoader > > always try first? > > > > Damn, I wish I would know this classloading stuff better. > > We all learned the way they work the hardway ;) and yes you > are thinking in the wrong direction, you think the delegation > model is a 2 way path. This is not, it's a no return path. > > > > > Do you have an idea why I cannot get logging output from the > > WebappClassLoaderS? > > see messages above. ;) > > > > > Sascha > > > > > -----Original Message----- > > > From: delbd [mailto:[EMAIL PROTECTED] > > > Sent: Thursday, June 02, 2005 2:32 PM > > > To: Tomcat Users List > > > Subject: Re: WebappClassLoader - don't understand what's happening > > > > > > Le Jeudi 2 Juin 2005 13:49, Herrmann, Sascha (GE > Healthcare) a écrit : > > > > Thanks for your reply. > > > > > > > > It could be. How is a class "pushed" to a shared library? > > > > > > Any library having static methods like > SomeLibraryClass.setXYZ(xyz); > > > SomeLibraryClass.getXYZ(xyz); > > > > > > > I used the following code: > > > > > > > > System.out.println( "BoneDBTransactionImpl2 LOADING > > > > ***************************************" ); System.out.println( > > > > "Thread Classloader is: " + > > > > Thread.currentThread().getContextClassLoader() ); > > > > > > System.out.println( > > > > > > > "Hash: " + > > > > Thread.currentThread().getContextClassLoader().hashCode() ); > > > > System.out.println( "Class: " + > > > > > > > Thread.currentThread().getContextClassLoader().getClass().getName() > > > ); > > > > > > > System.out.println( "--------------------------- " ); > > > > System.out.println( "Class Classloader is: " + > > > > BoneDBTransactionImpl2.class.getClassLoader() ); > > > > > > System.out.println( "Hash: > > > > " + BoneDBTransactionImpl2.class.getClassLoader().hashCode() ); > > > > System.out.println( "Class: " + > > > > > > > BoneDBTransactionImpl2.class.getClassLoader().getClass().getName() > > > ); > > > > > > > System.out.println( "BoneDBTransactionImpl2 LOADING > > > > ***************************************" ); > > > > > > Tss tss tss, the Threads instances are started by > catalina-http and > > > shared inside a Thread pool amongst tomcat application if am not > > > wrond, so i doubt usefull informations comes from it. > > > Only usefull information should comes from > > > BoneDBTransactionImpl2.class.getClassLoader() as this is the > > > classloader which will load any class needed by > > > BoneDBTransactionImpl2. > > > > > > > I put this into a static initializer block of a class that > > > > > > is in a jar > > > > > > > in both WEB_INF\lib directories. I also added this code the > > > > constructor of that class. And to make sure to see what > > > > > > loader belongs > > > > > > > to what app I also added the code to some methods of > > > > > > classes that are > > > > > > > either in app A or in app B and not in both. > > > > > > > > I start app A. The output shows that > > > > > > > > - the class is loaded in app A by WebappClassLoader with hash A > > > > - the instance is created in app A using the Class loaded by > > > > WebappClassLoader with hash A. - Thread context classloader is > > > > WebappClassLoader with hash A. > > > > > > > > Then I start app B. The output shows that > > > > > > > > - the instance is created in app B using the Class loaded by > > > > WebappClassLoader with hash A - Thread context classloader is > > > > WebappClassLoader with hash B. > > > > > > Strange indeed, so you mean when starting app B, the > static block of > > > BoneDBTransactionImpl2 is never executed? If that's the case this > > > indeed mean the class was already loaded before. Either this mean > > > you have another lib in webapp B requiring > > > BoneDBTransactionImpl2 and you didn't see the static init > message 50 > > > lines before ;), either you indeed have something shared. > > > > > > One easy way to check > > > In webapp A, create a servelt which will set to 1 a > static boolean > > > in > > > BoneDBTransactionImpl2 and in webapp B, set another servlet which > > > will read the value of this boolean. > > > first access B servlet to ensure boolean is set to false acces A > > > servlet to switch boolean to true re-access B servlet to check if > > > boolean has switched value in B webapp > > > > > > If that's the case, this really mean class is shared by > webapp class > > > loaders, serious problems ahead for tomcat team ;) > > > > > > > The class exists in jar files in both WEB-INF\lib > > > > > > directories, but not in > > > > > > > any other lib directory. And - if the class was loaded > by a shared > > > > classloader, shouldn't the xxx.class.getClassLoader() > return the > > > > StandardClassLoader? > > > > > > dunno > > > > > > > I must admit that I am not too familiar with the deeper > > > > > > concept of J2EE > > > > > > > classloading apart from the information found on some web pages. > > > > > > me too ;) however, separation in webapps mean every > ressource in a > > > .war is not to be shared with any other webapp. > > > > > > > So, if the class indeed is loaded by WebappClassLoader A, > > > > > > how can it be > > > > > > > "pushed" to become a shared one? And how can I prevent this > > > > > > from happening? > > > > > > > Or am I making a mistake reading the output? I am sure that > > > > > > the class is > > > > > > > not loaded again. > > > > > > see message above, i just didn't know how you concluded the class > > > was shared, one common error is to give an instance of > some object > > > to a shared library and retreive it in another webapp, not > > > understanding this object you are manipulating is a > stranger ;) not > > > your case scenario you describe. > > > > > > > I checked the sources in Apache's CVS. I noticed that there > > > > > > is quite some > > > > > > > debugging put into WebappClassLoader. But I can't get my > > > > > > server to log > > > > > > > these messages. I have the log4j and commons logging jars > > > > > > in my common\lib > > > > > > > directory and my log4j.properties (root logger set to > debug) in my > > > > common\classes directory. I also set the debug to "4" > > > > > > everywhere in my > > > > > > > server.xml. I see some catalina debug messages, but I > cannot see > > > > the messages from the WebappClassLoader. So what am I doing > > > > > > wrong? I believe > > > > > > > the debug output would be very helpful in understanding > the problem. > > > > > > Yes have same problem here to get usefull log messages > from Realms. > > > Seems you have to modify directly the logging level in your java > > > home, logging.properties (and setting it to debug for > whole jvm is > > > VERY verbose) > > > > > > > Sascha > > > > > > > > > -----Original Message----- > > > > > From: delbd [mailto:[EMAIL PROTECTED] > > > > > Sent: Thursday, June 02, 2005 12:33 PM > > > > > To: Tomcat Users List > > > > > Subject: Re: WebappClassLoader - don't understand what's > > > > > happening > > > > > > > > > > This indeed should not happen as this would break sun specs. > > > > > I would be quite surprised it it was at all possible > :/ How did > > > > > you conclude the webappclassloader is sharing the > class between > > > > > webapps in your case? > > > > > > > > > > Are you sure you are not mistakenly using a shared class? > > > > > > > > > > Not only does every webapp has his very own > webappclassloader, > > > > > but if you reload the webapp (using the manager/html > interface) > > > > > this should also create a new webclassloader and reload all > > > > > classes (did you check it was the case?). > > > > > > > > > > Am also using tomcat 5.5.7 here, with jdk 1.4.2_05-b04 and we > > > > > didn't notice such a problem. We can deploy several > webapps, all > > > > > using a library in WEB-INF/lib which is crating > singletons. All > > > > > webapp has it's own sets of singletons. > > > > > > > > > > Could it be that you are in fact doing such scenario? > > > > > > > > > > - create an object of class A in webapp1 using > > > > > webappclassloader1 > > > > > - push this object to some library shared between > > > > > webapplications > > > > > - retrieve the object from shared library in webapp2 > (as this is > > > > > via a shared library, it's possibile to do and you and up > > > > > manipulating in webapp2 an object who's classloader is > > > > > webappclassloader1) > > > > > - in webapp2, calls something like a.createB() to get > an object > > > > > of class B and be surprised that the class of B was created > > > > > using webappclassloader1 > > > > > > > > > > Le Jeudi 2 Juin 2005 10:59, Herrmann, Sascha (GE > > > > > > Healthcare) a écrit : > > > > > > We are facing a problem with Tomcats WebappClassLoader. > > > > > > We deploy several of our own applications on one > Tomcat server. > > > > > > > > > > > > It seems that the WebappClassLoaderS are not isolated but > > > > > > share classes instead. Why would that be? > > > > > > > > > > > > Judging from the (well, outdated) classloader > > > > > > documentation, this > > > > > > > > > should never happen. > > > > > > If an application tries to use a class, and the class is in > > > > > > > > > > a jar in > > > > > > > > > > > its WEB_INF\lib directory, then the class should be > > > > > > loaded by the > > > > > > > > > application's very own WebappClassLoader. It should not be > > > > > > > > > > available > > > > > > > > > > > to other WebappClassLoaderS, isn't that correct? I quote: > > > > > > > > > > > > "All unpacked classes and resources in the /WEB-INF/classes > > > > > > > > > > directory > > > > > > > > > > > of your web application archive, plus classes and > > > > > > resources in JAR > > > > > > > > > files under the /WEB-INF/lib directory of your web > application > > > > > > archive, are made visible to the containing web > > > > > > > > > > application, **but to no others**." > > > > > > > > > > > Instead of sharing the class, the second WebappClassLoader > > > > > > > > > > should load > > > > > > > > > > > the class again, shouldn't it? > > > > > > So why does a WebappClassLoader here re-use a class already > > > > > > > > > > loaded by > > > > > > > > > > > the WebappClassLoader of another application? > > > > > > > > > > > > We're running 5.5.7 on JDK 142_08. > > > > > > > > > > > > Thanks in advance! > > > > > > > > > > > > > > > > > > Sascha Herrmann > > > > > > Engineering (Java) > > > > > > GE Healthcare > > > > > > Technologies > > > > > > > -------------------------------------------------------------------- > > > - > > > > > > > > > To unsubscribe, e-mail: > > > > > > [EMAIL PROTECTED] > > > > > > > > > For additional commands, e-mail: > > > > > > [EMAIL PROTECTED] > > > > > > > > -- > > > > > David Delbecq > > > > > Royal Meteorological Institute of Belgium > > > > > > > > > > - > > > > > Is there life after /sbin/halt -p? > > > > > > > -------------------------------------------------------------------- > > > - > > > > > > > > To unsubscribe, e-mail: > > > > > [EMAIL PROTECTED] > > > > > For additional commands, e-mail: > > > > > > [EMAIL PROTECTED] > > > > > > > > > > -------------------------------------------------------------------- > > > - > > > > > > > To unsubscribe, e-mail: > [EMAIL PROTECTED] > > > > For additional commands, e-mail: > > > > [EMAIL PROTECTED] > > > > > > -- > > > David Delbecq > > > Royal Meteorological Institute of Belgium > > > > > > - > > > Is there life after /sbin/halt -p? > > > > > > > -------------------------------------------------------------------- > > > - To unsubscribe, e-mail: > [EMAIL PROTECTED] > > > For additional commands, e-mail: > [EMAIL PROTECTED] > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > -- > David Delbecq > Royal Meteorological Institute of Belgium > > - > Is there life after /sbin/halt -p? > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]