About classloader

J

jimlee2004

I have a couple question regarding classloader.
I did a search online but the more i read, the more confused I am.

For example, here is a doc that discuss the class loader.
http://www-128.ibm.com/developerworks/java/library/j-dyn0429/

The question I have is the following:

<quote>
Each class loader also keeps a reference to a parent class loader,
defining a tree of class loaders with the bootstrap loader at the root.
When an instance of a particular class (identified by name) is needed,
whichever class loader initially handles the request normally checks
with its parent class loader first before trying to load the class
directly. This applies recursively if there are multiple layers of
class loaders, so it means that a class will normally be visible not
only within the class loader that loaded it, but also to all descendant
class loaders. It also means that if a class can be loaded by more than
one class loader in a chain, the one furthest up the tree will be the
one that actually loads it.

There are many circumstances where multiple application classloaders
are used by Java programs. One example is within the J2EE framework.
Each J2EE application loaded by the framework needs to have a separate
class loader to prevent classes in one application from interfering
with other applications. The framework code itself will also use one or
more other class loaders, again to prevent interference to or from
applications. The complete set of class loaders make up a
tree-structured hierarchy with different types of classes loaded at
each level.
</quote>

1) Why multiple application classloaders is ever needed?
I thought the only thing needs to be done is just load the class, it
shouldn't matter which classloader loads it as the result matters not
the way how it is loaded.

2). When should I explicitly need to know about classloader? usually
the class is loaded for me by system. Could anybody give me some
example.

3). I saw some program that uses
ClassLoader cl = Thread.currentThread().getContextClassLoader();
and
ClassLoader.getSystemClassLoader().getResource(..)

what's the difference?


Thanks,
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

I have a couple question regarding classloader.
<quote>
Each class loader also keeps a reference to a parent class loader,
defining a tree of class loaders with the bootstrap loader at the root.
When an instance of a particular class (identified by name) is needed,
whichever class loader initially handles the request normally checks
with its parent class loader first before trying to load the class
directly. This applies recursively if there are multiple layers of
class loaders, so it means that a class will normally be visible not
only within the class loader that loaded it, but also to all descendant
class loaders. It also means that if a class can be loaded by more than
one class loader in a chain, the one furthest up the tree will be the
one that actually loads it.

There are many circumstances where multiple application classloaders
are used by Java programs. One example is within the J2EE framework.
Each J2EE application loaded by the framework needs to have a separate
class loader to prevent classes in one application from interfering
with other applications. The framework code itself will also use one or
more other class loaders, again to prevent interference to or from
applications. The complete set of class loaders make up a
tree-structured hierarchy with different types of classes loaded at
each level.
</quote>

1) Why multiple application classloaders is ever needed?
I thought the only thing needs to be done is just load the class, it
shouldn't matter which classloader loads it as the result matters not
the way how it is loaded.

If you have two web apps running on the same app server and both happen
to have a class test.Test, then I am sure both programmers prefer that
the app server treat them as two different classes.

If they are loaded with different classloaders, then that is
accomplished.
2). When should I explicitly need to know about classloader? usually
the class is loaded for me by system. Could anybody give me some
example.

Not often.

But if you need to work with app servers, then you do need
to understand the principles.
3). I saw some program that uses
ClassLoader cl = Thread.currentThread().getContextClassLoader();
and
ClassLoader.getSystemClassLoader().getResource(..)

what's the difference?

If I should guess, then the last one only search the classpath
for the system classloader.

Arne
 
T

Thomas Hawtin

ClassLoader cl = Thread.currentThread().getContextClassLoader();

Library code, say, may be shared between, say, web apps. The obvious way
to do this is have a single class loader for the library code and each
web app class loader have that as the parent. So library classes only
get loaded once.

If library code needs to load an a web app class, then using its own
class loader will not work. Thread.getContextClassLoader will give the
correct class loader (that of the web app).
ClassLoader.getSystemClassLoader().getResource(..)

This will get a resource from the classpath, rather than from any class
loaders the application/container has created.


Both of these methods require security permissions if they are not the
target class loader or a parent of it (or deeper ancestor).

Tom Hawtin
 
C

Chris Uppal

1) Why multiple application classloaders is ever needed?

Usually the reason is that the application is in some way pluggable. Anything
which loads and runs more-or-less arbitrary code is likely to need
classloaders. The main reasons are:
+ to better isolate each independent chunk of client code from
the other chunks.
+ to allow loaded classes to be unloaded again when they
are no longer needed or should be replaced.
+ to act as a "natural boundary" for security policy decisions.
Not all pluggable architectures need all, or even any, of the above; but many
do, and they will use classloaders.
2). When should I explicitly need to know about classloader? usually
the class is loaded for me by system. Could anybody give me some
example.

If you don't need those kinds of features then you can probably ignore
classloaders, /except/ that many Java programmers these days work in contexts
where their code is loaded by some sort of container (such as a web server).
In such cases a minimal knowledge of what classloaders do will help you to
understand the constraints on how you write your code and/or configure the
container.

-- chris
 
W

www.pulpjava.com

From: http://www.technicalfacilitation.com/get.php?link=classloading

-Cameron McKenzie

Free Java Certification Mock Exams: www.scja.com
Free Java and WebSphere Tutorials: www.mcnz.com
Free WebSphere Tutorials: www.pulpjava.com

www.cameronmckenzie.com www.examscam.com
@@@@@@@@@@@@@@@@@@@@@@@

What is a classloader?

Java applications run on a Java Virtual Machine (JVM).

Our J2EE applications run on a Java Virtual Machine as well, after all,
they are written in Java.

In the WebSphere world, the JVM that our J2EE applications run on is
often referred to as an 'application server,' since it is
responsible for serving our J2EE applications up to clients. Under the
covers though, an application server is nothing more than a souped-up
JVM running on the server.

If you are so inclined, you can even monitor the JVM responsible for
serving up your J2EE applications by bringing up the Windows Task
Manager and looking for the java.exe process that's hogging your
memory and consuming all of your processor's clock cycles. That's
the Java Virtual Machine that enables your WebSphere applications.

J2EE applications are written in Java, and JVMs have the job of running
and executing the Java code you have written.

When a client calls a Servlet, or an EJB calls the constructor of a
JavaBean, compiled Java code, also known as bytecode, must be loaded
and subsequently run on a JVM. Finding the appropriate Java bytecode
file, and throwing that bytecode onto a piping hot JVM is the job of a
very special, and extremely important component known as a classloader.

Classloaders locate Java bytecode files and load that Java bytecode on
the JVM. Without a classloaders, our J2EE applications simply would not
work.

Important Java classes that must be loaded onto the Java Virtual
Machine in order to get our applications to perform properly include:

F classes that implement the basic Java runtime environment such as
java.lang.Interger

F the code IBM has written to support and implement the J2EE
specification

F EJBs and the JavaBeans they use to implement complex business logic

F all of the Servlets, JSPs and helper classes that make our web
based applications behave the way they should

Understanding how classloaders work is one of the most important
aspects of WebSphere development, packaging and deployment.
Unfortunately, classloading is also one of the most misunderstood
aspects of J2EE development, leading to innumerable problems at both
runtime and design time.

To understand how the WebSphere runtime works, you must have a good
grasp of J2EE classloading.

What does a classloader do?

If a Java class is invoked and needs to be executed on a Java Virtual
Machine, a special Java component, called a classloader, is used to
find the Java class of interest, pull that Java class off of the file
system, and execute the bytecode of that class file on the Java Virtual
Machine.

A classloader is a special Java class file that is responsible for
loading other classes onto a Java Virtual Machine. While this may seem
simple and straightforward, don't get too cocky, 'cuz from here,
things get really complicated.

Life would be simple if there was just one, monolithic classloader that
did all of the classloading, but life just isn't that simple. There
are actually quite a number of different classloaders that work
together to locate and load Java bytecode. If you want to package your
applications properly, and avoid ClassNotFoundExceptions, you must be
familiar with the many WebSphere classloaders.

If Java classes are loaded by classloaders, and classloaders are Java
components, who loads the first classloader?

The old chicken and egg scenario, rearing its ugly head. If
classloaders are Java classes, and Java classes must be loaded onto a
JVM to run, how does the first classloader get loaded? It's a good
question.

When a JVM starts up, a special chunk of machine code runs that loads
the system classloader. This special hunk of machine code is known as
the null classloader.


The Null Classloader

The machine code that initializes the system classloader is referred to
as the null classloader because it is not a Java class at all, as are
all other classloaders. The null classloader is platform specific
machine instructions that kick off the whole classloading process.

All classloaders, with the exception of the null classloader, are
implemented as Java classes. Something must load the very first Java
classloader to get the process started. Loading the first pure Java
classloader is the job of the null classloader.

The null classloader also takes care of loading all of the code needed
to support the basic Java Runtime Environment (JRE), including classes
in the java.util and the java.lang packages.
The System Classloader: sun.misc.Launcher

The null classloader loads a true Java class of type sun.misc.Launcher.
The sun.misc.Launcher classloader prepares the basic Java Runtime
Environment needed by our application server.

Truth be told, the sun.misc.Launcher is actually made up of two inner
classes that do the actual classloading:

F sun.misc.Launcher$ExtClassLoader (parent)
F sun.misc.Launcher$AppClassLoader (system)

ExtClassLoader is the parent of AppClassLoader. Of the two, the inner
class, sun.misc.Launcher$AppClasLoader holds the true title of system
classloader

Quite appropriately, the sun.misc.Launcher is often referred to as the
bootstrap classloader as well as the system classloader. Any jars found
in the jre/lib directory of the JRE (not the WebSphere lib directory),
will be loaded by the system classloader. The system classloader is
tightly integrated with the components that implement the Java Runtime
Environment (JRE).
From within the WebSphere administrative console, you have the option
of adding Java files and resources to the WebSphere CLASSPATH. When
you add libraries to the WebSphere CLASSPATH, you are actually asking
the system classloader to load those classes when they are needed.
Appropriately, the system classloader is also known as the CLASSPATH
classloader.



Figure 19-1

Folders, files and Jars can be added to the WebSphere Class Path, and
alternatively to the WebSphere external classpath (ws.ext.dirs)



The system classloader is great at initializing the basic Java Runtime
Environment (JRE), but from a WebSphere and J2EE perspective, the
system classloader isn't nearly as sexy as the WebSphere extensions
classloader.
WebSphere Classloader: com.ibm.ws.bootstrap.ExtClassLoader

WebSphere doesn't want to step on any toes when it starts loading the
classes that it needs at runtime. Rather than using the system
classloader, WebSphere uses its own special classloader to load the
J2EE resources it needs.

When the system classloader is finished initializing, WebSphere takes
over, kicking off its own classloader.

The WebSphere classloader physically manifests itself as the Java class
of type com.ibm.ws.bootstrap.ExtClassLoader

Whereas the system classloader loads resources that support the Java
Runtime Environment (JRE), the WebSphere classloader is responsible for
initializing the J2EE runtime environment.

The WebSphere classloader, also known as the WebSphere extensions
classloader, loads all of the classes and files located in the \lib
directory of the WebSphere Application Server.

Figure 19-2 The WebSphere\AppServer\lib Directory

The WebSphere extensions classloaders looks for files stored in JAR
files in the lib directory of the Application Server.

You can also add files to the WebSphere classloader's classpath by
editing the WebSphere system property ws.ext.dirs.

Since the com.ibm.ws.bootstrap.ExtClassLoader loads all of the classes
required to support WebSphere and the J2EE specification, it is also
known as the WebSphere bootstrap classloader, as it essentially
bootstraps the WebSphere runtime environment.

The WebSphere j2ee.jar file, which is pretty much the bytecode
embodiment of the WebSphere Application Server, falls onto the
classpath of the WebSphere extensions classloader. The ExtClassLoader
pretty much loads WebSphere, and all of the peripheral components that
make WebSphere run.

So, a null classloader kick starts the JVM, a bootstrap classloader
loads classes needed by the basic Java Runtime Environment (JRE), and
then WebSphere takes over, using the extensions classloader to invite
all of its friends and family to come over and join in on the fun.

Table 19-1 Basic Classloader Hierarchy for WebSphere

Classloader Name


Implementation


Class Path

Null classloader


Machine Code


JRE Binaries

ã







Classpath classloader
or System Classloader


sun.misc.Launcher
sun.misc.Launcher


jre\lib

ã







WebSphere Extensions Classloader


com.ibm.ws.bootstrap.
ExtClassLoader


WebSphere\lib




The Application Classloader:
com.ibm.ws.classloader.CompoundClassLoader

Of course, our humble enterprise applications are by no means on the
same level as the ominous JVM and the ever so important WebSphere
Application Server. Correspondingly, our ear files are given their own
humble little classloaders, separate from that of the WebSphere
Application Server (WAS) and the Java Runtime Environment (JRE). A
special classloader, called the
com.ibm.ws.classloader.CompoundClassLoader, loads the resources found
packaged inside of our EAR files.

The CompondClassLoader can pull classes out of all of the different
modules in an ear file. By default, all utility Jar files, connector
modules, and EJB modules will have their classes loaded by the same
instance of a common compound classloader.

Since all of the utility Jars, EJB modules and connector modules
(notice that I didn't say web modules) share the same classloader
instance, files in one module of the ear will be visible to other
modules in the ear. This is a manifestation of the fact that a
classloader is entitled to pull classes out of any JAR on its
classpath.

Web Modules and the CompoundClassLoader

By default, web modules do not share the same classloader instance as
the other modules inside of an ear. Web modules get their own, private
instance of the CompoundClassLoader, which will only load classes that
exist within the web module. War files have their own private
classloader, ensuring that none of the other modules can peek inside
the war file for classes they might need.

¯


The classloader instance used by the web module is a sibling of the
instance used by the ear. As a result, a web module can see files
inside other jars in an ear. However, other modules cannot see classes
inside a war. Child classloaders can see classes on the classpath of
the parent. A parent cannot see classes on the classpath of a child.



What is the classloader hierarchy?

The picture I am trying to draw here is one of a crazy classloader
hierarchy, with the null classloader at the top, the classpath
classloader a little bit below, the WebSphere extensions classloader
directly underneath, the application classloader residing under the
WebSphere classloader, and a lonely web module classloader resting at
the very bottom.

In its simplest form, this is the classloader hierarchy for J2EE
applications deployed to the WebSphere Application Server.

Which classloaders will load my Java classes at runtime?

When a classloader, such as the CompoundClassLoader for a web module,
looks for a Java file, where do you think it looks?

Logically, you'd assume that the web module classloader would look in
the web module for a given Java file or Servlet, wouldn't you? Well,
this type of foolish thinking is wrong, and has caused all sorts of
deployment problems.

By default, each classloader, with the exception of the
ExtJarClassLoader, is set up with a 'PARENT_FIRST' configuration. A
PARENT_FIRST configuration forces a classloader to ask its parent to
try and load a given a Java class first.

If a web module needs some chunk of Java code that is sitting right
there in the \lib directory of the war, the web module classloader
first asks its parent classloader, the application classloader, to find
the Java class file.

And what do you think the application classloader does when asked to
load a Java class file?

When the application classloader is asked to load a class, it delegates
to its parent, the WebSphere extensions classloader, to see if it can
find and load the file.

By now, you can probably guess where the WebSphere extensions
classloader goes before looking on its own local classpath for the file
in question. Yes, it defers to the system classloader, which then
defers to the null classloader. The null classloader then tries to find
the Java class of interest on its own local classpath, and if it does
find the file, it will load it on the JVM.

So, what happens when the system classloader can't load the class
your looking for?

Of course, there's a good chance that the Java class of interest will
not be on the system or null classloader's classpath. After all, why
would you put a class required by your web module in the lib directory
of the JRE upon which WebSphere runs?

When we hit the top of the classloading hierarchy, the class-finding
baton gets passed back down the ladder, one classloader at a time,
opposite to the order in which the hierarchy was climbed.



Figure 19-3 Inverted Classloading Hierarchy for an EJB

When loading EJB module classes, the CompoundClassLoader delegates to
its parent according to the rules of classloading.

Classloader for the EJB module:

++com.ibm.ws.classloader.CompoundClassLoader

++++ com.ibm.ws.classloader.ExtJarClassLoader

++++++ com.ibm.ws.classloader.ProtectionClassLoader

++++++++ com.ibm.ws.bootstrap.ExtClassLoader

++++++++++ sun.misc.Launcher$AppClassLoader

++++++++++++ sun.misc.Launcher$ExtClassLoader

++++++++++++++ null


Figure 19-4 Inverted Classloading Hierarchy for a Servlet

Notice the subtle difference between the classloader hierarchy for a
web component, as opposed to an EJB component as described in figure
19-3

Classloader for the web module:

++com.ibm.ws.classloader.CompoundClassLoader

++++com.ibm.ws.classloader.JarClassLoader

++++++com.ibm.ws.classloader.ExtJarClassLoader

++++++++com.ibm.ws.classloader.ProtectionClassLoader

++++++++++ com.ibm.ws.bootstrap.ExtClassLoader

++++++++++++ sun.misc.Launcher$AppClassLoader

++++++++++++++ sun.misc.Launcher$ExtClassLoader

++++++++++++++++ null

If the null or system classloader can't find the class file of
interest, the WebSphere classloader then starts looking for it, and if
the WebSphere classloader can't find the class file, the classloader
with authority over the ear starts looking, and if the classloader for
the ear can't find the file, it's up to the web module to locate
it, which in the case of a Servlet or JSP, was the classloader that was
asked to load the file in the first place!

If the class in question was in the lib directory of the web module to
begin with, it's not until the entire hierarchy has exhaustively been
explored, that the web module classloader can finally load the file of
interest.

What happens when none of the classloaders can locate a particular Java
class file?

A Java file might be found by any classloader in the hierarchy, but it
is the first classloader that finds the file, starting from the top of
the hierarchy down, that actually does the loading.

If a class file is found, life is good, and our Java applications will
hopefully run fine. If none of the classloaders can find the file, then
we run head first into the java.lang.ClassNotFoundException.

Why the Hierarchy of Classloaders?

While the behavior of the classloading hierarchy may seem a little bit
convoluted, it is actually quite a good idea, and for the most part, it
works quite well.

Imagine for a second that some cheeky monkey wrote their own
implementation of the java.lang.Integer class,­ hacking around, really
messing up the implementation of this fundamental Java class.

Even if a developer packaged this file right inside of an ear that was
designed to use it, the new implementation of the java.lang.Integer
class would never get loaded by any of the classloaders.

The java.lang.Integer class already exists on the classpath of the null
classloader, right at the top of the classloading hierarchy, so if this
new, hacked implementation of the java.lang.Integer class was packaged
along with an ear or war file, the hacked implementation would never be
loaded. Regardless of the number of applications that might be deployed
with a fraudulent implementation of the java.lang.Integer class, only
the proper class, the one loaded by the null classloader, would ever be
used.

The classloading hierarchy provides a secure, consistent and reliable
class loading behavior.

Does the classloading hierarchy ever cause problems?

Now, while your basking in the glow of the effectiveness of the Java
classloading hierarchy, think about this alternative scenario:

Perhaps one of your developers has gone hog wild, XML crazy, and has
been using the latest, greatest version of the Xerces XML parser in all
of their web applications. The developer correctly packages the files
required to implement the XML parser in the lib directory of the war,
right alongside all of the Servlets and helper classes that need to use
the xerces parser. WebSphere shouldn't have any problem finding these
Xerces-XML parser files, right?

Well, the developer may have configured everything to work 'honkie
dorie' in the development tool, but as soon as the application goes
into production, all sorts of errors will be generated about deprecated
methods, classes not conforming, or even that certain methods being
invoked don't actually exist.

This is where things get interesting. J

The IBM implementation of the WebSphere Application Server relies on a
boatload of JAR files and Java files, many of which come from common,
open source projects such as xerces, xalan and ant.

If you check out the 'lib' directory of the application server,
which is the directory the WebSphere extensions classloader pulls
classes from, you'll discover a plethora of JAR files and Java
classes that just might conflict with your attempt to use the latest
and greatest technologies on the open market.

In this particular scenario, the WebSphere extensions classloader is
picking up its own, older version of the xerces.jar file. None of the
calls the developers are making to the latest xerces implementation are
working properly, despite having placed the latest xerces.jar file
right there in the lib directory of the web module. The older
xerces.jar file in the lib directory of the application server trumps
any xerces.jar file found below it on the classpath hierarchy.

What do I do when WebSphere is loading classes from the wrong jar file?

In this scenario, we have a conflict between the xerces.jar file in the
WebSphere lib directory, and the xerces.jar file in the lib directory
of the web module. What do we do when we want to use the latest and
greatest edition of a technology that WebSphere uses behind the scenes?

Whatever you do, do not replace the existing JAR file in WebSphere lib
directory with the latest and greatest edition. That will hose
everything.

But at the same time, you can't just throw away all of the work your
development team has done using the latest and greatest frameworks from
Apache.

So the question now becomes: 'has all of the development done using
the latest version of the xalan.jar file been in vain?' Well, not
necessarily.

Although 'parent first' is the default classloading behavior,
WebSphere allows you to configure your classloaders to employ a
'parent-last' classloading configuration instead.

What is 'parent-last' classloading?

A 'parent-last' configuration, which is set on a per classloader
level, instructs a classloader to look locally for resources before
passing the job off to a parent. With a parent-last configuration, a
classloader will only delegate to the parent classloader if the Java
file in question is not on its own local classpath.

If your developers have been working with the latest version of xerces,
but WebSphere keeps using the older version that sits in its lib
directory, you can configure the classloader for the web module, or
even for the ear, to use a parent last configuration when looking for
Java files to load.



Table 19-2 Classloader Hierarchy

Classloader


Purpose


Default Scope

null classloader


Machine code that initializes the Java environment


classes from the basic Java runtime libraries

System classloader

sun.misc.Launcher


Loads classes used by the basic Java Runtime Environment


Classes found in the lib directory of the JRE

WebSphere Bootstrap Classloader

ExtClassLoader


Loads the J2EE and WebSphere runtime environment


The WebSphere \lib directory

Security Classloader

ProtectionClassLoader


Loads security related Java classes, I think


Not sure L

External Jar Classloader

ExtJarClassLoader


Loads common classes needing a PARENT_LAST mode of delegation


The \lib\app directory of the application server

Non WAR Classloader

CompoundClassLoader


Used to load files inside modules of an ear, with the exception of the
web module


This instance of the CompoundClassLoader has scope in all non-web
modules of an EAR

Internal Jar Classloader

JarClassLoader


Makes classes in non-web modules of an EAR visible to web module
components

Parent of the WAR classloader


This instance of the CompoundClassLoader has scope in all non-web
modules of an EAR

WAR Classloader

CompoundClassLoader


Loads the web components and Java code found in the WAR


Individual WAR files within an EAR

When a web module is configured to use a parent last configuration, if
the xerces.jar file is placed in the lib directory of the war, the war
classloader will pull classes from the web module first, and defer to
the WebSphere extensions classloader, which pulls in the older version
of xerces, later.

Furthermore, when WebSphere itself needs the older version of the
xerces.jar file, it will use the WebSphere classloader, which will look
into its local lib directory and find the older version. Both WebSphere
and the war file will be using the correct, yet different, versions of
the same set of classes.



Figure 19-5 Classloader Settings

An ear can have a module or application classloader policy. It can also
have a parent_first or parent_last classloader mode.

What is a module or application classloader policy?

It was stated earlier that the web module, by default, uses an instance
of the CompoundClassLoader that is separate from the other modules in
the ear. This is the default classloader policy for an ear, known as
module centric classloading.

However, you can switch from module centric classloading to application
centric classloading. By making this change, all modules in an ear,
including web and ejb modules, will use the same classloader instance.
The web module will not be given a separate and unique classloader

The implication of an application classloader policy is that any module
will be able to see classes in any other module in the ear, including
web modules. With a module centric classloader policy, ejbs and utility
classes cannot see classes inside of a WAR.

How can two versions of the same class be loaded on the same JVM?

People find it difficult to get their head around the fact that it is
possible to load two or more different versions of the same class onto
a JVM. Not only is this possible, it is extremely common.

One of the rules of classloading is that a classloader can never use or
access classes loaded by a classloader beneath it in the hierarchy. If
a web module configured with a parent-last configuration loads a class
called com.pulpjava.User, and then the application classloader, or even
the WebSphere classloader, is asked to load the com.pulpjava.User
class, so long a version of the class file can be found on their
classpath, which is indeed different from the classpath of the web
module, a separate instance of the same class will be loaded onto the
JVM.

You must be very careful where you package your Java classes, because
placing a file in a war file, an EJB module, a utility jar inside of an
ear, or even on the WebSphere classpath, will have a significant impact
on classloading, class instantiation, and class visibility.

Is it possible to have multiple instances of a singleton running on a
JVM?

A singleton is a Java class that is programmed in such a way that
ensures only one instance of that class is ever loaded onto the JVM. A
singleton is one of the most common design patterns in existence, and
is extremely effective when trying to mitigate access to various
resources.

However, if a singleton class is packaged and placed on the classpath
of different classloaders, it is indeed possible to have many instances
of a singleton running. If a singleton is managing some mission
critical resources, be sure that your applications are packaged in such
a way that the classloading hierarchy won't start spinning off
multiple instances.

Why am I getting Serialization errors when I run my applications?

Another interesting problem that can arise from having a different
classloader for each application and web module, especially when you
configure a parent-last configuration, is conflicting versions of the
same class being loaded.

For example, say a web module was using com.pulpjava.User version 1.1,
and an EJB module in another project was using com.pulpjava.User
version 1.2. You can only have one version of a JavaBean loaded on a
JVM right? Wrong!

Even though both applications might be running on the same JVM, if the
web module was configured with a parent-last classloading
configuration, and it then tried to pass a User object to the EJB
module, there would be all sorts of serialization and version errors,
because both modules would be using different versions of the same
JavaBean.

Both modules may have a User class, and both modules can load that
class onto the JVM. However, when they try to pass the User object back
and forth, runtime exceptions will be thrown because the versions are
out of sync.

This type of scenario can produce a variety of cryptic error messages,
and troubleshooting comes down to figuring out which module is loading
which version of the class.

The solution usually requires redeploying the applications in such a
way that they can communicate with each other properly. This may be
implemented by repackaging the applications to ensure that both EJB and
web modules are using the same classloader to load the
com.pulpjava.User class.

An alternative solution is to play around with the serialization id of
the com.pulpjava.User class to make the JVM think the two classes are
the same. Regardless, solving serialization id errors are never fun.

What is class visibility?

A classloader can never use or access a class loaded by a classloader
below itself on the hierarchy. This can create a bizarre scenario where
a web module might be able to find a Java class named User, but an EJB,
which uses a different classloader, gets a ClassNotFoundException when
trying to access the exact same class.

Reckoning with the fact that all of this is happening on the same JVM,
I usually just start shouting at the JVM, demanding to know why it can
find the file just fine in the web module, but not in the EJB module.
For what it's worth, I've never found shouting at a JVM to be
successful way of resolving ClassNotFoundException, but it does tend to
make me feel better.

Class visibility describes which classes can be seen by which
classloader, and subsequently, which J2EE components.

Troubleshooting classloader issues is extremely difficult without a
fundamental understanding of how classloading works.

Sometimes I can access a class, other times I can't!

An interesting scenario happens when you've got three classes all
accessing a fourth. Let's just say the forth is a database driver.

If the driver is packaged in the root of the ear, the Servlet will be
able to call on the driver when it runs. An EJB in the same project
will also be able to call on the driver when it runs. However, a
common component packaged on the WebSphere extension classpath, will
NOT be able to call upon the driver and will instead cough up a
ClassNotFoundException.

Again, you will be able to prove that indeed the driver can be found by
the JVM, since both your EJB and your Servlets will be able to use it.
You can even profile the driver on the JVM and prove without a doubt
that not only can the JVM find the class, but the JVM can load it and
run it without any hint of a glitch.

It's only when the component packaged at the ws.ext level tries to
make a call to the component below it on the classloader hierarchy that
your application runs into a problem.

It's a hard lesson to learn, but a classloader cannot make calls to
classes that are on the path of a classloader below it on the
classloader hierarchy.

Where is the best place to package common components?

In the preceding scenario, you could do one of two things to eliminate
the ClassNotFoundException:

F move the driver up to the ws.ext directory along with the common
component
F move the common component down into the ear along with driver

Personally, I would do both. Typically, drivers go on the ws.ext
classpath, and common components go into the root of the ear.

How do we best package our applications?

So, with all of these classloaders and various classpath issues, the
question becomes, "how should we package our applications, and where
should we place various jar files such as common components, drivers,
utility classes and others?"

The first rule is: all of your EJBs go in EJB modules, and all of your
Servlets should go in you web modules. Unfortunately, from there it
gets a little tricky.

For example, where should you put the jar files that have the
implementation of your custom tags? Custom tags make JSP development
much easier, and they are a web centric component, so conventional
wisdom says you should put it in the lib directory of your web module.
But what if your ear file has four or even fourteen web modules that
use those custom tags? Should you duplicate the jar file that contains
the code for your custom tags and place a copy of that jar in each of
the fourteen web modules, or should you put just one central copy
inside of the ear.

Should you duplicate the file 14 times, or should you have every module
reference just one, single copy? Duplication seems like such a waste,
doesn't it?

Placing the jar containing the Java code that implements the customs
tags in the root of the ear means you have one central location for you
code, and when the application runs, only one instance of a class will
be created to handle the requests, despite having many modules. That
definitely sounds like the best alternative, but to be honest, that's
not the alternative I'd go with.

Personally, I'd place a copy of the jar file in each war. That means
the code is redundantly copied from war to war fourteen times, which in
itself is a bad thing. It also means that I'll have extra instances
of common tag classes running, which means a slight degradation in
performance. But for my money, I'd rather duplicate that common code
in each war.

The long-term cost of any project is not the cost of getting it up and
running, but the cost of managing and maintaining that application over
time.

Having every web module pointing to the same custom tag code is going
to make future version changes a real headache. If I update the custom
tag code at the ear level, then every web module must upgrade to use
the newer version as well. Expecting every web module in the
application to update at the same time is unreasonable.

It would be much easier to place this jar file in each war, and when a
new version of the library comes out, the battle to migrate the
application can be waged on a war-by-war basis. After all, when was the
last time every single application in your enterprise migrated at
exactly the same time? Most likely never.

Figure 19-6

Your common components should go in the ear, along with war files and
ejb modules.


How should you package common utility components?

Now let's think about a general set of common components. Say for
instance, your company has a set of common components that include a
User object, Employee interface and a bunch of other useful and
reusable objects that get used in all of your EJB and web modules.
Where would place a jar file like this?

Smart money says you should put one copy in the root of the ear, and
not duplicate the common component jar file in each of your web and EJB
modules.

Now I know that this directly contradicts the maintainability argument
of the previous scenario, but the fact is, with common components, you
often need to enforce a common versioning.

A common design pattern has EJBs and Servlets passing JavaBeans back
and forth to each other. These JavaBeans must be at the same version
level, and have the same set of properties and methods; otherwise, the
process of marshalling these objects back and forth between EJBs and
Servlets is going to fail.

Packaging these common components in the root of the ear will help
maintain a common version across all EJB and Web modules in the
application.

Keep in mind that you may, and likely will, have components from one
ear file calling components in another ear file, and they'll probably
pass data back and forth using classes defined in your common
components jar file. If this is the case you could still run into the
problem of having version incompatibilities between jar files, forcing
you to upgrade the common components in several ear files at the same
time.

For me, that's a chance I'm willing to take, and I'm going to
depend on my architects to have articulated the application
interdependency effectively and in excruciating detail within the
design documents.

Of course, if you want to be absolutely positive all enterprise
applications are using the same version of your common components, you
could remove the common-components.jar file out of the root of the ear,
and place the common components in the ws.ext directory, but I think
that's a pretty big trigger to pull as well.

What are the drawbacks to using the WebSphere extensions classloader
for common files?

One thing that should be stated when talking about classloaders and the
extensions directory is that any component that does a call back into a
web module or an ejb module must be placed inside the ear and not on a
classpath outside of the ear.

For example, say a Servlet calls on a helper class that uses an EJB.
If that helper class were placed outside of the ear, the Servlet would
be calling a component that exists outside of the application context.
If the helper class then made a call back into the ear, to interact
with an EJB for instance, that callback would be treated as a
completely anonymous invocation from a component outside of the
application's context.

This poses a real problem, especially if we have security turned on or
transactions running. By leaving the ear, the entire security context
of the Servlet will be lost, and the resulting call will end up with an
error to the effect that an unauthenticated user cannot access the EJB,
despite the fact that the client was challenged when the Servlet was
first invoked.

If you're having problems with security, and you're getting errors
indicating that a secured resource is being invoked by an anonymous
user, despite being challenged every time you try to access the
component in question, then a component outside of the ear is making a
callback.

This scenario can be especially frustrating due to the fact that when
security is not on, everything works fine. Only when you turn security
on does a problem like this rear its ugly head.

So, any components making a callback into the ear must be placed within
the ear if we wish for those components to maintain their security or
transactional contexts.

What should we place on the ws.ext classpath?

The extensions classpath is a great place to throw any commonly used
components that do not make callbacks into a J2EE application. This
includes elements such as common parsers and database drivers.

Every application in the enterprise should be connecting to the same
version of db2. Everyone should be connecting to the same mail server.
If the mail server changes, or the version of DB2 is updated, all of
the applications will likely be updated at the same time. Placing
database drivers for db2 in the ws.ext classpath will make updating the
database drivers for all of your applications easy and manageable.

There is an art to effectively packaging your J2EE applications. With
an understanding of how the various WebSphere and JVM classloaders
work, you will make deployment easier, and avoid those tedious
ClassNotFoundExceptions at runtime
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top