Java Classloading
Classloaders are a fundamental module of the Java language. A
classloader is a part of the Java virtual machine (JVM) that loads
classes into memory; a classloader is responsible for finding and
loading class files at run time. Every successful Java programmer needs
to understand classloaders and their behavior. This section provides an
overview of Java classloaders.
Java Classloader Hierarchy
Classloaders contain a
hierarchy with parent classloaders and child classloaders. The
relationship between parent and child classloaders is analogous to the
object relationship of super classes and subclasses. The bootstrap
classloader is the root of the Java classloader hierarchy. The Java
virtual machine (JVM) creates the bootstrap classloader, which loads
the Java development kit (JDK) internal classes and java.* packages
included in the JVM. (For example, the bootstrap classloader loads
java.lang.String.)
The extensions classloader is
a child of the bootstrap classloader. The extensions classloader loads
any JAR files placed in the extensions directory of the JDK. This is a
convenient means to extending the JDK without adding entries to the
classpath. However, anything in the extensions directory must be
self-contained and can only refer to classes in the extensions
directory or JDK classes.
The system classpath
classloader extends the JDK extensions classloader. The system
classpath classloader loads the classes from the classpath of the JVM.
Application-specific classloaders (including WebLogic Server
classloaders) are children of the system classpath classloader.
Note: |
What BEA refers to as a “system classpath classloader” is often
referred to as the “application classloader” in contexts outside of
WebLogic Server. When discussing classloaders in WebLogic Server, BEA
uses the term “system” to differentiate from classloaders related to
Java EE applications or libraries (which BEA refers to as “application
classloaders”). |
Loading a Class
Classloaders use a delegation model when loading a class. The
classloader implementation first checks its cache to see if the
requested class has already been loaded. This class verification
improves performance in that its cached memory copy is used instead of
repeated loading of a class from disk. If the class is not found in its
cache, the current classloader asks its parent for the class. Only if
the parent cannot load the class does the classloader attempt to load
the class. If a class exists in both the parent and child classloaders,
the parent version is loaded. This delegation model is followed to
avoid multiple copies of the same form being loaded. Multiple copies of
the same class can lead to a ClassCastException.
Classloaders ask their parent
classloader to load a class before attempting to load the class
themselves. Classloaders in WebLogic Server that are associated with
Web applications can be configured to check locally first before asking
their parent for the class. This allows Web applications to use their
own versions of third-party classes, which might also be used as part
of the WebLogic Server product. The prefer-web-inf-classes Element section discusses this in more detail.
prefer-web-inf-classes Element
The weblogic.xml Web application deployment descriptor contains a <prefer-web-inf-classes> element (a sub-element of the <container-descriptor>
element). By default, this element is set to False. Setting this
element to True subverts the classloader delegation model so that class
definitions from the Web application are loaded in preference to class
definitions in higher-level classloaders. This allows a Web application
to use its own version of a third-party class, which might also be part
of WebLogic Server. See
“weblogic.xml Deployment Descriptor Elements.”
When using this feature, you must be careful not to mix instances
created from the Web application’s class definition with issuances
created from the server’s definition. If such instances are mixed, a
ClassCastException results.
Listing 8-1 illustrates the prefer-web-inf-classes element, its description and default value.
Listing 8-1 prefer-web-inf-classes Element
Changing Classes in a Running Program
WebLogic Server allows you to
deploy newer versions of application modules such as EJBs while the
server is running. This process is known as hot-deploy or hot-redeploy
and is closely related to classloading.
Java classloaders do not have
any standard mechanism to undeploy or unload a set of classes, nor can
they load new versions of classes. In order to make updates to classes
in a running virtual machine, the classloader that loaded the changed
classes must be replaced with a new classloader. When a classloader is
replaced, all classes that were loaded from that classloader (or any
classloaders that are offspring of that classloader) must be reloaded.
Any instances of these classes must be re-instantiated.
In WebLogic Server, each
application has a hierarchy of classloaders that are offspring of the
system classloader. These hierarchies allow applications or parts of
applications to be individually reloaded without affecting the rest of
the system. WebLogic Server Application Classloading discusses this topic.
WebLogic Server Application Classloading
The following sections provide an overview of the WebLogic Server application classloaders:
Overview of WebLogic Server Application Classloading
WebLogic Server classloading is centered on the concept of an
application. An application is normally packaged in an Enterprise
Archive (EAR) file containing application classes. Everything within an
EAR file is considered part of the same application. The following may
be part of an EAR or can be loaded as stand-alone applications:
- An Enterprise JavaBean (EJB) JAR file
- A Web application WAR file
- A resource adapter RAR file
If you deploy an EJB and a
Web application separately, they are considered two applications. If
they are deployed together within an EAR file, they are one
application. You deploy modules together in an EAR file for them to be
considered part of the same application.
Every application receives
its own classloader hierarchy; the parent of this hierarchy is the
system classpath classloader. This isolates applications so that
application A cannot see the classloaders or classes of application B.
In hierarchy classloaders, no sibling or friend concepts exist.
Application code only has visibility to classes loaded by the
classloader associated with the application (or module) and classes
that are loaded by classloaders that are ancestors of the application
(or module) classloader. This allows WebLogic Server to host multiple
isolated applications within the same JVM.
Application Classloader Hierarchy
WebLogic Server automatically
creates a hierarchy of classloaders when an application is deployed.
The root classloader in this hierarchy loads any EJB JAR files in the
application. A child classloader is created for each Web application
WAR file.
Because it is common for Web
applications to call EJBs, the WebLogic Server application classloader
architecture allows JavaServer Page (JSP) files and servlets to see the
EJB interfaces in their parent classloader. This architecture also
allows Web applications to be redeployed without redeploying the EJB
tier. In practice, it is more common to change JSP files and servlets
than to change the EJB tier.
The following graphic illustrates this WebLogic Server application classloading concept.
If your application includes servlets and JSPs that use EJBs:
- Package the servlets and JSPs in a WAR file
- Package the Enterprise JavaBeans in an EJB JAR file
- Package the WAR and JAR files in an EAR file
- Deploy the EAR file
Although you could deploy the
WAR and JAR files separately, deploying them together in an EAR file
produces a classloader arrangement that allows the servlets and JSPs to
find the EJB classes. If you deploy the WAR and JAR files separately,
WebLogic Server creates sibling classloaders for them. This means that
you must include the EJB home and remote interfaces in the WAR file,
and WebLogic Server must use the RMI stub and skeleton classes for EJB
calls, just as it does when EJB clients and implementation classes are
in different JVMs. This concept is discussed in more detail in the next section Application Classloading and Pass-by-Value or Reference.
Note: |
The Web application classloader contains all classes for the Web
application except for the JSP class. The JSP class obtains its own
classloader, which is a child of the Web application classloader. This
allows JSPs to be individually reloaded. |
Custom Module Classloader Hierarchies
You can create custom classloader hierarchies for an application
allowing for better control over class visibility and reloadability.
You achieve this by defining a classloader-structure element in the
weblogic-application.xml deployment descriptor file.
The following diagram
illustrates how classloaders are organized by default for WebLogic
applications. An application level classloader exists where all EJB
classes are loaded. For each Web module, there is a separate child
classloader for the classes of that module.
For simplicity, JSP classloaders are not described in the following diagram.
This hierarchy is optimal for
most applications, because it allows call-by-reference semantics when
you invoke EJBs. It also allows Web modules to be independently
reloaded without affecting other modules. Further, it allows code
running in one of the Web modules to load classes from any of the EJB
modules. This is convenient, as it can prevent a Web module from
including the interfaces for EJBs that is uses. Note that some of those
benefits are not strictly Java EE-compliant.
The ability to create custom module classloaders provides a mechanism
to declare alternate classloader organizations that allow the
following:
- Reloading individual EJB modules independently
- Reloading groups of modules to be reloaded together
- Reversing the parent child relationship between specific Web modules and EJB modules
- Namespace separation between EJB modules
Declaring the Classloader Hierarchy
You can declare the classloader hierarchy in the WebLogic-specific application deployment descriptor weblogic-application.xml.
The DTD for this declaration is as follows:
Listing 8-2 Declaring the Classloader Hierarchy
The
top-level element in weblogic-application.xml includes an optional
classloader-structure element. If you do not specify this element, then
the standard classloader is used. Also, if you do not include a
particular module in the definition, it is assigned a classloader, as
in the standard hierarchy. That is, EJB modules are associated with the
application Root classloader, and Web application modules have their
own classloaders.
The classloader-structure
element allows for the nesting of classloader-structure stanzas, so
that you can describe an arbitrary hierarchy of classloaders. There is
currently a limitation of three levels. The outermost entry indicates
the application classloader. For any modules not listed, the standard
hierarchy is assumed.
Note: |
JSP classloaders are not included in this definition scheme. JSPs
are always loaded into a classloader that is a child of the classloader
associated with the Web module to which it belongs. |
For more information on the DTD elements, refer to Enterprise Application Deployment Descriptor Elements.
The following is an example of a classloader declaration (defined in
the classloader-structure element in weblogic-application.xml):
Listing 8-3 Example Classloader Declaration
The
organization of the nesting indicates the classloader hierarchy. The
above stanza leads to a hierarchy shown in the following diagram.
User-Defined Classloader Restrictions
User-defined classloader
restrictions give you better control over what is reloadable and
provide inter-module class visibility. This feature is primarily for
developers. It is useful for iterative development, but the reloading
aspect of this feature is not recommended for production use, because
it is possible to corrupt a running application if an update includes
invalid elements. Custom classloader arrangements for namespace
separation and class visibility are acceptable for production use.
However, programmers should be aware that the Java EE specifications
say that applications should not depend on any given classloader
organization.
Some classloader hierarchies
can cause modules within an application to behave more like modules in
two separate applications. For example, if you place an EJB in its own
classloader so that it can be reloaded individually, you receive
call-by-value semantics rather than the call-by-reference optimization
BEA provides in our standard classloader hierarchy. Also note that if
you use a custom hierarchy, you might end up with stale references.
Therefore, if you reload an EJB module, you should also reload calling
modules.
There are some restrictions
to creating user-defined module classloader hierarchies; these are
discussed in the following sections.
Servlet Reloading Disabled
If you use a custom classloader hierarchy, servlet reloading is disabled for Web applications in that particular application.
Nesting Depth
Nesting is limited to three levels (including the application classloader). Deeper nestings lead to a deployment exception.
Module Types
Custom classloader hierarchies are currently restricted to Web and EJB modules.
Duplicate Entries
Duplicate entries lead to a deployment exception.
Interfaces
The standard WebLogic Server
classloader hierarchy makes EJB interfaces available to all modules in
the application. Thus other modules can invoke an EJB, even though they
do not include the interface classes in their own module. This is
possible because EJBs are always loaded into the root classloader and
all other modules either share that classloader or have a classloader
that is a child of that classloader.
With the custom classloader
feature, you can configure a classloader hierarchy so that a callee’s
classes are not visible to the caller. In this case, the calling module
must include the interface classes. This is the same requirement that
exists when invoking on modules in a separate application.
Call-by-Value Semantics
The standard classloader
hierarchy provided with WebLogic Server allows for calls between
modules within an application to use call-by-reference semantics. This
is because the caller is always using the same classloader or a child
classloader of the callee. With this feature, it is possible to
configure the classloader hierarchy so that two modules are in separate
branches of the classloader tree. In this case, call-by-value semantics
are used.
In-Flight Work
Be aware that the classloader
switch required for reloading is not atomic across modules. In fact,
updates to applications in general are not atomic. For this reason, it
is possible that different in-flight operations (operations that are
occurring while a change is being made) might end up accessing
different versions of classes depending on timing.
Development Use Only
The development-use-only
feature is intended for development use. Because updates are not
atomic, this feature is not suitable for production use.
Individual EJB Classloader for Implementation Classes
WebLogic Server allows you to
reload individual EJB modules without requiring you to reload other
modules at the same time and having to redeploy the entire EJB module.
This feature is similar to how JSPs are currently reloaded in the
WebLogic Server servlet container.
Because EJB classes are
invoked through an interface, it is possible to load individual EJB
implementation classes in their own classloader. This way, these
classes can be reloaded individually without having to redeploy the
entire EJB module. Below is a diagram of what the classloader hierarchy
for a single EJB module would look like. The module contains two EJBs
(Foo and Bar). This would be a sub-tree of the general application
hierarchy described in the previous section.
To perform a partial update of files relative to the root of the exploded application, use the following command line:
Listing 8-4 Performing a Partial File Update
After the -redeploy command, you provide a list of files relative to
the root of the exploded application that you want to update. This
might be the path to a specific element (as above) or a module (or any
set of elements and modules). For example:
Listing 8-5 Providing a List of Relative Files for Update
Given
a set of files to be updated, the system tries to figure out the
minimum set of things it needs to redeploy. Redeploying only an EJB
impl class causes only that class to be redeployed. If you specify the
whole EJB (in the above example, anotherejb) or if you change and
update the EJB home interface, the entire EJB module must be
redeployed.
Depending on the classloader
hierarchy, this redeployment may lead to other modules being
redeployed. Specifically, if other modules share the EJB classloader or
are loaded into a classloader that is a child to the EJB's classloader
(as in the WebLogic Server standard classloader module) then those
modules are also reloaded.
Application Classloading and Pass-by-Value or Reference
Modern programming languages
use two common parameter passing models: pass-by-value and
pass-by-reference. With pass-by-value, parameters and return values are
copied for each method call. With pass-by-reference, a pointer (or
reference) to the actual object is passed to the method. Pass by
reference improves performance because it avoids copying objects, but
it also allows a method to modify the state of a passed parameter.
WebLogic Server includes an
optimization to improve the performance of Remote Method Interface
(RMI) calls within the server. Rather than using pass by value and the
RMI subsystem’s marshalling and unmarshalling facilities, the server
makes a direct Java method call using pass by reference. This mechanism
greatly improves performance and is also used for EJB 2.0 local
interfaces.
RMI call optimization and
call by reference can only be used when the caller and callee are
within the same application. As usual, this is related to classloaders.
Because applications have their own classloader hierarchy, any
application class has a definition in both classloaders and receives a
ClassCastException error if you try to assign between applications. To
work around this, WebLogic Server uses call-by-value between
applications, even if they are within the same JVM.
Note: |
Calls between applications are slower than calls within the same
application. Deploy modules together as an EAR file to enable fast RMI
calls and use of the EJB 2.0 local interfaces. |
Using a Filtering Classloader
In WebLogic Server, any .jar file present in the system classpath is
loaded by the WebLogic Server system classloader. All applications
running within a server instance are loaded in application classloaders
which are children of the system classloader. In this implementation of
the system classloader, applications cannot use different versions of
third-party jars which are already present in the system classloader.
Every child classloader asks the parent (the system classloader) for a
particular class and cannot load classes which are seen by the parent.
For example, if a class called com.foo.Baz
exists in both $CLASSPATH
as well as the application EAR, then the class from the $CLASSPATH
is loaded and not the one from the EAR. Since weblogic.jar
is in the $CLASSPATH
, applications can not override any WebLogic Server classes.
The following sections define and describe how to use a filtering classloader:
What is a Filtering ClassLoader
The FilteringClassLoader
provides a mechanism for you to configure deployment descriptors to
explicitly specify that certain packages should always be loaded from
the application, rather than being loaded by the system classloader.
This allows you to use alternate versions of applications such as
Xerces and
Ant.
The FilteringClassLoader
sits between the application classloader and the system. It is a child
of the system classloader and the parent of the application
classloader. The FilteringClassLoader
intercepts the loadClass(String
className
)
method and compares the className
with a list of packages specified in weblogic-application.xml
file. If the package matches the className
, the FilteringClassLoader
throws a ClassNotFoundException
. This exception notifies the application classloader to load this class from the application.
Configuring a FilteringClassLoader
To configure the FilteringClassLoader
to specify a certain package is loaded from an application, add a prefer-application-packages
descriptor element to the weblogic-application.xml
which details the list of packages to be loaded from the application.
The following example specifies that org.apache.log4j.* and antlr.*
packages are loaded from the application, not the system classloader:
Resource Loading Order
The resource loading order is the order in which java.lang.ClassLoader
methods getResource()
and getResources()
return resources. When filtering is enabled, this order is slightly
different from the case when filtering is disabled. Filtering is enabled
implies that there are one or more package patterns in the FilteringClassLoader
.
Without any filtering (default), the resources are collected in the
top-down order of the classloader tree. For instance, if Web (1)
requests resources, the resources are grouped in the following order:
Sys (3), App (2) and Web(1). See Figure 8-5.
System (3)
|
App (2)
|
Web (1)
To be more explicit, given a resource /META-INF/foo.xml
which exists in all the classloaders, would return the following list of URLs:
When filtering is enabled, the resources from the child of the FilteringClassLoader
(an application classloader) down to the calling classloader are returned before the ones from the system classloader. In Figure 8-6,
if the same resource existed in all the classloaders (D), (B) and (A)
one would get them in the following order if requested by the Web
classloader:
Note: |
The resources are returned in the default Java EE delegation model beneath the FilteringClassLoader . Only the resources from the parent of the FilteringClassLoader are appended to the end of the enumeration being returned. |
System (D)
|
FilteringClassLoader (filterList := x.y.*) (C)
|
App (B)
|
Web (A)
If the application classloader requested the same resource, the following order would be obtained.
For getResource()
, only the first descriptor is returned and getResourceAsStream()
returns the inputStream
of the first resource.
Resolving Class References Between Modules and Applications
Your applications may
use many different Java classes, including Enterprise Beans, servlets
and JavaServer Pages, utility classes, and third-party packages.
WebLogic Server deploys applications in separate classloaders to
maintain independence and to facilitate dynamic redeployment and
undeployment. Because of this, you need to package your application
classes in such a way that each module has access to the classes it
depends on. In some cases, you may have to include a set of classes in
more than one application or module. This section describes how
WebLogic Server uses multiple classloaders so that you can stage your
applications successfully.
About Resource Adapter Classes
Each resource adapter now
uses its own classloader to load classes (similar to Web applications).
As a result, modules like Web applications and EJBs that are packaged
along with a resource adapter in an application archive (EAR file) do
not have visibility into the resource adapter’s classes. If such
visibility is required, you must place the resource adapter classes in
APP-INF/classes. You can also archive these classes (using the JAR
utility) and place them in the APP-INF/lib of the application archive.
Make sure that no
resource-adapter specific classes exist in your WebLogic Server system
classpath. If you need to use resource adapter-specific classes with
Web modules (for example, an EJB or Web application), you must bundle
these classes in the corresponding module’s archive file (for example,
the JAR file for EJBs or the WAR file for Web applications).
Packaging Shared Utility Classes
WebLogic Server provides a
location within an EAR file where you can store shared utility classes.
Place utility JAR files in the APP-INF/lib directory and individual
classes in the APP-INF/classes directory. (Do not place JAR files in
the /classes directory or classes in the /lib directory.) These classes
are loaded into the root classloader for the application.
This feature obviates the
need to place utility classes in the system classpath or place classes
in an EJB JAR file (which depends on the standard WebLogic Server
classloader hierarchy). Be aware that using this feature is subtly
different from using the manifest Class-Path described in the following
section. With this feature, class definitions are shared across the
application. With manifest Class-Path, the classpath of the referencing
module is simply extended, which means that separate copies of the
classes exist for each module.
Manifest Class-Path
The Java EE specification
provides the manifest Class-Path entry as a means for a module to
specify that it requires an auxiliary JAR of classes. You only need to
use this manifest Class-Path entry if you have additional supporting
JAR files as part of your EJB JAR or WAR file. In such cases, when you
create the JAR or WAR file, you must include a manifest file with a
Class-Path element that references the required JAR files.
The following is a simple manifest file that references a utility.jar file:
In the first line of the manifest file, you must always include the
Manifest-Version attribute, followed by a new line (CR | LF |CRLF) and
then the Class-Path attribute. More information about the manifest
format can be found at: http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#JAR
The manifest Class-Path entries refer to other archives relative to the
current archive in which these entries are defined. This structure
allows multiple WAR files and EJB JAR files to share a common library
JAR. For example, if a WAR file contains a manifest entry of y.jar,
this entry should be next to the WAR file (not within it) as follows:
The manifest file itself should be located in the archive at META-INF/MANIFEST.MF.
For more information, see
http://java.sun.com/docs/books/tutorial/jar/basics/manifest.html.
Sharing Applications and Modules By Using Java EE Libraries
Java EE libraries
provide an easy way to share one or more different types of Java EE
modules among multiple Enterprise Applications. A Java EE library is a
single module or collection of modules that is registered with the Java
EE application container upon deployment. For more information, see Creating Shared Java EE Libraries and Optional Packages.
Adding JARs to the System Classpath
WebLogic Server includes a lib
subdirectory, located in the domain directory, that you can use to add
one or more JAR files to the WebLogic Server system classpath when
servers start up. The lib
subdirectory is
intended for JAR files that change infrequently and are required by all
or most applications deployed in the server, or by WebLogic Server
itself. For example, you might use the lib
directory to store third-party utility classes that are required by all
deployments in a domain. You can also use it to apply patches to
WebLogic Server.
The lib
directory is not recommended as a general-purpose method for sharing a
JARs between one or two applications deployed in a domain, or for
sharing JARs that need to be updated periodically. If you update a JAR
in the lib
directory, you must reboot all
servers in the domain in order for applications to realize the change.
If you need to share a JAR file or Java EE modules among several
applications, use the Java EE libraries feature described in Creating Shared Java EE Libraries and Optional Packages.
To share JARs using the lib
directory:
- Shutdown all servers in the domain.
- Copy the JAR file(s) to share into a
lib
subdirectory of the domain directory. For example:
Note: |
WebLogic Server must have read access to the lib directory during startup. |
Note: |
The Administration Server does not automatically copy files in the lib
directory to Managed Servers on remote machines. If you have Managed
Servers that do not share the same physical domain directory as the
Administration Server, you must manually copy JAR file(s) to the domain_name /lib directory on the Managed Server machines. |
- Start the Administration Server and all Managed Servers in the domain. WebLogic Server appends JAR files found in the
lib
directory to the system classpath. Multiple files are added in alphabetical order.