Scope of static classes

G

GaryM

I have a question that relates to a web application I deployed under
Jetty, but more generally, has highlighted a misconception I have held
on static classes.

I have implemented the Jakarta Commons Database Connection Pooling. To
facilate the web app, I wrote a class with static methods to provide,
amongst other things, a connection from the pool. I initialize the
static class in the main app, then start the Jetty Server.

My rationale was that the static class would be subsequently accessable
to the Jetty server as they are all under one VM. I was surprised that
this was not the case and in fact I needed to initialize the static
class in the web app itself. If I simply add a context (as opposed to a
Web Application) to the server this approach works.

So my questions are:

1. How does this work, ie. how is possible to limit the scope of static
class? Is a new VM created to run the web app?

2. Is there a recommended method for initialzing the web app aside from
checking for initialization in every JSP?
 
M

Michiel Konstapel

I have a question that relates to a web application I deployed under
Jetty, but more generally, has highlighted a misconception I have held on
static classes.

I have implemented the Jakarta Commons Database Connection Pooling. To
facilate the web app, I wrote a class with static methods to provide,
amongst other things, a connection from the pool. I initialize the static
class in the main app, then start the Jetty Server.

My rationale was that the static class would be subsequently accessable
to the Jetty server as they are all under one VM. I was surprised that
this was not the case and in fact I needed to initialize the static class
in the web app itself. If I simply add a context (as opposed to a Web
Application) to the server this approach works.

So my questions are:

1. How does this work, ie. how is possible to limit the scope of static
class? Is a new VM created to run the web app?

No, but the web apps are loaded by different class loaders, in effect
giving them a whole different set of classes. Apparently, the utility class
loaded by your main app is not visible to the web app classes. Their
version is loaded by a Jetty class loader.
2. Is there a recommended method for initialzing the web app aside from
checking for initialization in every JSP?

If you have the initialization in a static initializer block, it'll be run
the first time the class is used (actually when it's loaded, but accessing
it will probably what triggers that).
HTH,
Michiel
 
J

John C. Bollinger

Michiel said:
No, but the web apps are loaded by different class loaders, in effect
giving them a whole different set of classes. Apparently, the utility
class loaded by your main app is not visible to the web app classes.
Their version is loaded by a Jetty class loader.

You (GaryM) probably worked it out from Michiel's response, but to lay
it out directly: every class in the JVM is scoped to the ClassLoader
that loaded it. By use of different ClassLoaders the VM may contain
many distinct copies of the "same" class.
If you have the initialization in a static initializer block, it'll be
run the first time the class is used (actually when it's loaded, but
accessing it will probably what triggers that).

Michiel offers excellent advice there.

Also, most servlet containers / Java app servers offer spaces where you
can put classes and jars that are to be accessible to all webapps in the
container. If Jetty does this (I don't know for sure) and if it is
useful to try to avoid multiple copies of the class in the VM, then you
could try putting the class (and its dependencies) into Jetty's version
of that space. For this kind of thing, though, you are well advised to
avoid any need for external initialization of the class.


John Bollinger
(e-mail address removed)
 
D

Doug Pardee

Michiel Konstapel said:
If you have the initialization in a static initializer block, it'll be run
the first time the class is used (actually when it's loaded, but accessing
it will probably what triggers that).

No, no, NO!

PLEASE read Chapter 12 of the Java2 Language Specification. It can be
found at http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html
-- initialization of classes is NOT triggered by loading.

Loading and initialization of classes are TWO DIFFERENT PROCESSES in
Java. In fact, they are just two of the processes that are part of
preparing a class to be used:
o loading -- this process is implemented by the ClassLoader
o linking (includes verification, preparation, and resolution)
o initialization

Loading and initialization can occur at very different times. Classes
can be preloaded (and prelinked) by the JVM, and they can be preloaded
by the ClassLoader, but they can NEVER be pre-initialized. The point
in time where a class is initialized is clearly called out by section
12.4.1. It can be paraphrased as:
o when an instance is created ('new')
o when a static method is called
o when a non-constant static field is accessed
o when certain reflection methods are used

Section 12.4.1 goes on to say, "A class or interface will not be
initialized under any other circumstance." This is important because
it GUARANTEES that Java will always use "lazy initialization" of
static fields and static blocks.
 
G

GaryM

Also, most servlet containers / Java app servers offer spaces
where you can put classes and jars that are to be accessible to
all webapps in the container. If Jetty does this (I don't know
for sure) and if it is useful to try to avoid multiple copies of
the class in the VM, then you could try putting the class (and its
dependencies) into Jetty's version of that space. For this kind
of thing, though, you are well advised to avoid any need for
external initialization of the class.

Thanks Michael and John. I cannot find anywhere in Jetty where this
could occur, but I have submitted my question to the Jetty mailing
list.

Failing this, it seems I'll need to check the class is initialized at
every valid entry point to the web site.
 
M

Michiel Konstapel

Thanks Michael and John. I cannot find anywhere in Jetty where this could
occur, but I have submitted my question to the Jetty mailing list.

Failing this, it seems I'll need to check the class is initialized at
every valid entry point to the web site.

That's not very elegant... How about having one servlet in your web app
configured as <load-on-startup> in web.xml and running the initialization
from that servlet's init() method? That is, if the static initializer won't
work for you (for example, because you need to be able to propagate
exceptions somewhere).
Michiel
 
M

Michiel Konstapel

No, no, NO!

PLEASE read Chapter 12 of the Java2 Language Specification. It can be
found at
http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html
-- initialization of classes is NOT triggered by loading.

Loading and initialization of classes are TWO DIFFERENT PROCESSES in
Java. In fact, they are just two of the processes that are part of
preparing a class to be used:

<snip>

Thanks for the correction.
HAND,
Michiel
 
G

GaryM

That's not very elegant... How about having one servlet in your
web app configured as <load-on-startup> in web.xml and running the
initialization from that servlet's init() method? That is, if the
static initializer won't work for you (for example, because you
need to be able to propagate exceptions somewhere).

Thanks once more. The web.xml method is nice and worked like a charm. I
confess I do not fully understand the static initializer approach.
Would I not need the static initializer block at each entry point,
getting back to the inelegant solution?
 
J

John C. Bollinger

GaryM said:
Thanks once more. The web.xml method is nice and worked like a charm. I
confess I do not fully understand the static initializer approach.
Would I not need the static initializer block at each entry point,
getting back to the inelegant solution?

(1) Although a load-on-startup servlet for webapp initialization is an
oft-suggested technique (which apparently works most of the time) the
Right Thing for webapp initialization is a ServletContextListener
implementation. This must be declared in web.xml as a listener.

(2) A static initializer block is executed once, when the class is
initialized [thanks, Doug], which necessarilly happens before any
instance is created or any static member is accessed by another class.
The syntax looks like this:

public class MyClass {

public static int myInt;
public static Object someObject;

// Here's the static initializer:
static {
myInt = SomeOtherClass.staticMethodReturningInt();
someObject = new Integer(myInt);
AUtilityClass.doSomethingInteresting();
}

[...]
}

A static initializer can contain most otherwise legal Java code, but
among the restrictions are that it is not permitted to throw any checked
exceptions, it may not contain a return statement, and [naturally] it
may not use the this or super keywords. For more information see JLS
8.7 and other sections referenced there.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top