You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Miles Daffin <md...@infpwr.com> on 2001/08/20 13:22:51 UTC

RE: ClassLoader & Reloading issues: static values

This is an interesting one.

I had assumed that statics were a nono in webapps
because they broke Context encapsulation.

It appears, however, that you can have your cake
and eat it. At least in TC 3.2.1.

I declared a public static String in a Base servlet
and built the host webapp twice, with two different
values in this String into 2 war files with different
names. After starting TC I could see that the same
static String had different values in the 2 Contexts.

I have just reread the 2.2 spec and do not recall seeing
anything that suggested that compliant containers must
behave like this. Did I miss something?

Given that it seems one can safely use statics in webapps,
is there anything now to be said against this?


Miles Daffin

> -----Original Message-----
> From: craigmcc@localhost [mailto:craigmcc@localhost]On Behalf Of Craig
> R. McClanahan
> Sent: Monday, August 20, 2001 4:26 AM
> To: 'tomcat-user@jakarta.apache.org'
> Subject: Re: ClassLoader & Reloading issues
>
>
>
>
> On Mon, 20 Aug 2001, Andrés Aguiar wrote:
>
> > I have a JAR file in my web-inf\lib directory that has an
> object pool. The
> > pool is kept as a singleton, so, I have a static member with it.
> >
>
> And because the class itself is loaded by the webapp class loader, the
> static is in fact global *only* within this particular web app.
>
> > The problem is that when a class in web-inf\classes is
> reloaded, it seems to
> > use a new classloader,
>
> That's correct -- there is no way to "unload" a class in Java except for
> throwing away the class loader that loaded it (and therefore all of the
> classes loaded by that old class loader).
>
> > so the static member is gets not the same as it was,
> > and I end having multiple object pool instances.
> >
> > If I put the .JAR in the Tomcat classpath, it obviously works ok.
> >
> > The problem is that I must keep running in the same
> servlet-engine instance
> > several applications each of which could a have a different
> version of my
> > .JAR file, so I can't put it in the classpath.
> >
> > The same happens running the app in Resin.
> >
> > Now, in the servlet spec says:
> >
> > 'Although a Container Provider implementation of a class
> reloading scheme
> > for ease of development is not required, any such
> implementation must ensure
> > that all servlets, and classes that they may use, are loaded in
> the scope of
> > a single class loader. This requirement is needed to guarantee that the
> > application will behave as expected by the Developer.
> >
> > As a development aid, containers are encouraged to maintain the full
> > semantics of notification to session binding listeners if they
> > determine to terminate sessions in order to reload classes.
> >
> > Previous generations of containers created new class loaders to load a
> > servlet, distinct from class loaders used to load other
> servlets or classes
> > used in the servlet context. This could cause object references within a
> > servlet context to point at unexpected classes or objects, and cause
> > unexpected behavior.'
> >
>
> Very early containers used a different class loader for every servlet, not
> for every web app.  To ensure consistent behavior, this is no longer
> allowed.
>
> > I'm not sure if this paragraph is referring to the case I'm
> describing, but
> > if not, it seems pretty close...
> >
> > Any ideas? Is this the way it's supposed to work?
> >
>
> Yes, it is working the way it is supposed to work (given the limitations
> on what Java allows for class "reloading").
>
> What you need to do is make sure that your class is aware of when the
> application is being shut down and started up again, so that you can save
> away the contents of the object pool (at shutdown time) and restore them
> (at startup time).  At shutdown time, you'll need to save the state of the
> object pool in some fashion that can be used to reconstruct it upon the
> subsequent startup.  A common technique is to serialize the pooled objects
> to a sequential file (Tomcat 4 does this with all of the currently active
> sessions when you shut it down or do an application reload).
>
> To make sure your object pool class is notified, you've got a couple of
> choices:
>
> * [Servlet 2.3 only] You can use the new application event listener
>   APIs and make sure your class is notified on the application startup
>   and application shutdown events.  This will work in Tomcat 4 and other
>   containers that implement the new servlet spec.
>
> * You might have a servlet defined as <load-on-startup> that initializes
>   the object pool in its init() method and saves it away in its destroy()
>   method.  This depends on the servlet container *not* removing this
>   servlet from service at any time *other* than application shutdown --
>   while commonly implemented that way, this is not guaranteed by the
>   servlet spec (it would work in all versions of Tomcat, though).
>
> > Thanks.
>
> Craig McClanahan
>
>
>


Re: ClassLoader & Reloading issues: static values

Posted by Endre Stølsvik <En...@Stolsvik.com>.
On Mon, 20 Aug 2001, Miles Daffin wrote:

| This is an interesting one.
|
| I had assumed that statics were a nono in webapps
| because they broke Context encapsulation.

Easiest way to create e.g. Connection pools and the like.

| I declared a public static String in a Base servlet
| and built the host webapp twice, with two different
| values in this String into 2 war files with different
| names. After starting TC I could see that the same
| static String had different values in the 2 Contexts.

Why not, they're living in different classloaders..?

|
| I have just reread the 2.2 spec and do not recall seeing
| anything that suggested that compliant containers must
| behave like this. Did I miss something?

Probably something about ClassLoaders.. The two classes (instances of
them) are loaded with different ClassLoaders, and are therefore two
entirely different classes, try to for example to cast between them! (This
one was kind of hard to understand, I couldn't cast my object to the User
class, even if object.getClass().getName() returned User!!).


-- 
Mvh,
Endre


RE: ClassLoader & Reloading issues: static values

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Mon, 20 Aug 2001, Miles Daffin wrote:

> This is an interesting one.
> 
> I had assumed that statics were a nono in webapps
> because they broke Context encapsulation.
> 
> It appears, however, that you can have your cake
> and eat it. At least in TC 3.2.1.
> 

Actually, in all containers that support servlet 2.2 or greater.  But you
do have to be slightly careful in one case.

Many containers (including Tomcat) let you put JAR files into a common
directory (for Tomcat, it's "lib") that are available to *all*
webapps.  Because this is outside the language of the spec, behavior
differs somewhat -- but in most cases, statics declared by a class loaded
from this global directory *are* global to all webapps.

If you want your webapps to be truly independent, then make sure that you
load all your classes from /WEB-INF/classes or /WEB-INF/lib.

> I declared a public static String in a Base servlet
> and built the host webapp twice, with two different
> values in this String into 2 war files with different
> names. After starting TC I could see that the same
> static String had different values in the 2 Contexts.
> 
> I have just reread the 2.2 spec and do not recall seeing
> anything that suggested that compliant containers must
> behave like this. Did I miss something?
> 

It's slightly indirect, but it's there.

Basically, a container is required to load all components of a web
application with a single class loader, and to use a different class
loader for each web app.  Now, if you go back to the Java Language
Specification, you'll find that the scope of a static is the class loader
it was loaded from.

Stand-alone Java applications tend not to notice any difference, because
they tend to be executed in a single class loader that was initialized
from the CLASSPATH environment variable.  In that scenario, statics are
truly global to the entire app.

> Given that it seems one can safely use statics in webapps,
> is there anything now to be said against this?
> 

Just the usual cautions about variables that can be updated from anywhere,
which can make debugging more interesting.

> 
> Miles Daffin
> 

Craig McClanahan