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.
> >

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

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

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

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

Regards,
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

Reply via email to