Hello Vladimir,

Thank you for your help with classloaders. :)

I tried to put my "shared" classes in the classpath. But this approach
failed too. I cannot understand.

In this case my "shared" classes loaded by "Bootstrap class loader
(Java system classes)" and in case any references to them should use
above classloader. Even in case servlet reloading. Of course, I removed
these classes from web-inf/classes directory.

May-be I need to load this "shared" class before loading my servlet, that uses
this "shared" object? May-be it is loaded by "Webapp class loader
(contents of WEB-INF/classes)"? I don't know.

This situation doesn't hurt me. I just want to know, how other Tomcat
users deal with such problem. I think many projects use "shared"
objects between servlets. This situation may be happen only in "development
stage" and never in "production". But let me know, how do you deal
with it?



Wednesday, March 14, 2001, 7:10:01 PM, you wrote:

VG> Bo Xu wrote:
>> 
>> Andrey Myatlyuk wrote:
>> 
>> > Hello Vladimir,
>> >
>> > Thank you for your help.
>> >
>> > And I'm still have some questions.
>> >
>> > Why do we need to implement "some interface"? java.io.Serializable I
>> > think? But anyway I implemented this interface - it doesn't work. This
>> > approach works for EJB. :)
>> >
>> > And my question is: Is there any way to use "some shared" object with
>> > reloadable servlets without Tomcat restart?
>> >
>> > Thanks.
>> >

VG> After reading this message and some thinking I can say that the problem is
VG> harder than I thought. There's no way to trick it, at least there's no interface
VG> you can create/implement to fix it... And of course it wasn't the Serializable
VG> one...
VG> Sorry, for misleading... But... what about this:

VG> Object _statesBean =
VG>      getServletContext().getAttribute(StatesBean.STATES_BEAN_NAME);

VG> Class sBeanClazz = _statesBean.getClass();
VG> Method m = sBeanClazz.getMethod("foo", new Class[] {/*args*/});
VG> m.invoke(_statesBean, new Object{ /*params*/ });

VG> he-he, ugly :) Not sure if it'll work...

VG> Regards,
VG> VG.

>> > Wednesday, March 14, 2001, 3:16:45 PM, you wrote:
>> >
>> > VG> I think you're experiencing a standard Java class loader problem.
>> > VG> Java treats classes loaded into different classloaders as different
>> > VG> classes, even though they share the same full. qual. name.
>> > VG> Your recompiled servlets are reloaded by a brand new class loader
>> > VG> to make sure the old classes are garbage collected. What you get
>> > VG> from the context is actuially an instance of a class loaded into
>> > VG> a different classloader, and (StatesBean) part in your statement
>> > VG> causes StatesBean to be loaded again by this new classloader that
>> > VG> reloaded your servlet, so
>> > VG> VM complains that you cannot cast objects since it thinks they
>> > VG> are instances of 2 completely different classes. No matter where
>> > VG> you place your files you'll have the same problem.
>> >
>> > VG> You can avoid this problem by writing some extra code and have your
>> > VG> bean to implement some interface.... Extra work, just restart
>> > VG> Tomcat every time...
>> >
>> > VG> Regards,
>> > VG> VG.
>> >
>> > VG> Andrey Myatlyuk wrote:
>> > >>
>> > >> Hello Tomcat users,
>> > >>
>> > >> I'm in a trouble. I share some object(StatesBean) between servlets. And when I
>> > >> recompile _servlet_, I got ClassCastException about shared object.
>> > >>
>> > >> _statesBean=
>> > >>     (StatesBean)getServletContext().getAttribute(StatesBean.STATES_BEAN_NAME);
>> > >>
>> > >>
>> > >> Classfile for this object is placed in the same directory, where
>> > >> servlets do - web-inf/classes. Where I need to place classfile for
>> > >> this object to prevent Tomcat exceptions?
>> > >>
>> > >> Of course, if I reload Tomcat everything is OK.
>> > >>
>> > >> Thank you in advance!
>> > >>
>> > >> --
>> > >> Best regards,
>> > >>  Andrey                            mailto:[EMAIL PROTECTED]
>> > [...]
>> 
>> Hi :-)  I am not sure, I guess:
>>  * perhaps the problem is:
>>     - let use suppose:   classloaderA -> classA -> instanceA
>>       then you "setAttribute"  instanceA into ServletContext of
>>       this wepapp, so now ServletContext holds a reference to
>>       instanceA.
>>     - after a while, your Sevlet class is reloaded, with
>>       jakarta-tomcat-4.0-b1, now classloaderA is not there,
>>       so classA is not there, But instanceA is there: because
>>       at least there is One reference of instanceA is being holded
>>       by ServletContext, so it will not be GCed, and getAttribute()
>>       will not return null.
>>    - but now instanceA doesn't has "its original class" and "its
>>      original classloader", I am not sure, but I guess perhaps it is
>>      the reason.
>> 
>> *  IMHO, I guess:  if you can find a way to load classA from a
>>     special classloader which will not be destroyed when/even if
>>     your Servlet class is reloaded, then you can solve the problem.
>>     It means that our Servlet class and some Helper classes are
>>     loaded by several classloaders in "diferent layer". if we don't
>>     want to keep a Attribute "across Servlet reloading", perhaps
>>     we don't need to it; but if we want, and we are sure that the
>>     "webapp classloader" will be destroyed and re-made, than I
>>     guess perhaps we have to use classloaders which are in
>>     "diferent layer".
>> 
>> *   the following is a good email about the classloader:
>> 
>> //************  <good email> ************************
>> On Sat, 10 Mar 2001, David Wall wrote:
>> 
>> > There appears to be a serious problem with the classpath/classloader with
>> > Tomcat 3.2.1.
>> >
>> > It may be related to the Jasper engine, which outputs a dynamic classpath
>> > name that includes all of the classes and jars in the WEB-INF directory, as
>> > expected.  But is the same classloader used when servlets are loaded at
>> > startup according to the web.xml file?
>> >
>> 
>> The same class loader is used to load all classes within a particular web
>> application, but there is more to the story than that.  See below.
>> 
>> > Anyway, I'm not sure where the problem resides, but I have found that by
>> > setting the CLASSPATH to the same thing Jasper sets up (specifically those
>> > files in WEB-INF/classes and WEB-INF/lib), my beans will no longer complain
>> > about unknown classes.
>> >
>> > But unfortunately, this "fix" doesn't really work because apparently they
>> > really are loaded by different classloaders, so they are not the same
>> > classes within the JVM.  This causes problems for classes that appear to
>> > have been initialized, but then magically are not when loaded through the
>> > other classloader.
>> >
>> 
>> The most common cause for this is actually a developer error.  Before
>> explaining how this can be true, let's look a little at how class loading
>> actually works in Tomcat (the details do ***not*** necessarily apply to
>> any other servlet container, because standard behavior is not specified).
>> 
>> There is actually a hierarchy of class loaders created when Tomcat is
>> running:
>> - Bootstrap class loader (Java system classes)
>> - Extensions class loader (JAR files from $JAVA_HOME/jre/lib/ext)
>> - System class loader (contents of CLASSPATH at startup time)
>> - Webapp class loader (contents of WEB-INF/classes and WEB-INF/lib
>>   for your particular web application)
>> 
>> Now, when your servlet class is loaded, Tomcat asks the webapp class
>> loader to load it.  Following the standard Java delegation model, the web
>> app class loader first asks it's parent class loader to try to find the
>> class -- and so on up the hierarchy.  If your servlet class is actually in
>> WEB-INF/classes or WEB-INF/lib, all of these attempts to delegate upwards
>> will fail.  Therefore, the web app class loader will load the class
>> itself.
>> 
>> The same thing happens for every other class that your servlet references
>> -- it gets loaded by whichever class loader finds that class.  If the load
>> happens from a class loader *above* the calling class's class loader, that
>> is fine.  However, trouble occurs if you try the opposite direction,
>> because there are no links *downward* in the class loader hierarchy.
>> 
>> Consider what happens if you put your servlet class into $TOMCAT_HOME/lib
>> (so that it gets added to the system class loader at startup time).  When
>> you reference the servlet, it gets loaded by the system class loader --
>> not the web app class loader.  So, if it tries to refer to a JavaBean
>> class you have stored in WEB-INF/classes or WEB-INF/lib.  What
>> happens?  You've got it:  ClassNotFoundException.  Because the servlet was
>> loaded from the system class loader, it can only look *up* the hierarchy
>> rather than *down*.
>> 
>> > Anyway, is there anybody looking into this?  I know I've seen several
>> > postings complaining about classpath problems that are likely related to
>> > this.  Has it been fixed in 3.2.2?
>> >
>> 
>> The moral of the story is that you should follow the following steps to
>> completely avoid class loading problems in your web apps, and guarantee
>> that your apps will be portable to other servlet containers:
>> 
>> * Do not rely on system extensions in $JAVA_HOME/jre/lib/ext.  If you
>>   do, those classes are *not* allowed to reference any classes on the
>>   system class path, or inside your web application.
>> 
>> * Do not rely on adding classes onto your CLASSPATH (or putting them in
>>   $TOMCAT_HOME/lib) before starting Tomcat.  Such classes will have
>>   problems with downward references, as described above.  Also, support
>>   for shared library classes is ***not*** required by the servlet spec,
>>   so you cannot count on this facility in a portable app.
>> 
>> * Put all classes your application needs into WEB-INF/classes, or
>>   in JAR files unde WEB-INF/lib.  In this way, they will all be loaded
>>   by the same class loader and not have any referencing problems.
>> 
>> There are other specific issues with specific libraries, and there are
>> some changes in how class loading works in Tomcat 4.0, but the above
>> outline identifies what to do about the majority of class loading issues
>> in servlet containers.
>> 
>> > Thanks,
>> > David
>> >
>> 
>> Craig McClanahan
>> 
>> //************  </good email> ************************
>> 
>> Bo    ^_^
>> Mar.14, 2001



-- 
Best regards,
 Andrey                            mailto:[EMAIL PROTECTED]


Reply via email to