In this recipe, we will examine how classes are loaded and the class loader hierarchy typically found in a Java EE server. An understanding of this process also explains the dependencies found between modules. In addition, a class not found type of exception is not uncommon. Understanding the loading process will help resolve these types of errors.
Not all of the application's classes are loaded immediately upon deployment of an application. Classes are generally loaded as needed at runtime when a client needs it. When an instance of a class is created, the class must be in memory.
It is not uncommon for an application to generate a ClassNotfoundException
or a ClassNoDefException
during execution. Thus, it can be important to understand the class loading process to correct these types of problems. Most environments use what is called Parent-First Delegation class loading process. The basic steps of this process include:
By checking for the presence of a class in a cache, the loading process can be sped up. By using the parent loader, we can be confident that malicious classes were not inadvertently loaded. If desired, it is possible to create your own class loader.
The actual loading process is vendor-specific. There are no specifications on how class loading is to be accomplished by a Java EE server. This limitation can make it difficult to port an application to a different server if the order of class loading is important.
One way of determining when a class loads is to use a static initialization block for the class and displaying a message indicating that the class has been loaded. This block is executed only once when the class is loaded. However, this technique can only be applied to those classes whose source code is available. The JVM -verbose option can also be used which will show when each class is loaded. However, as the option name implies, the output can be verbose and hard to follow.
The overall process of class loading begins when a JVM starts up. The CLASSPATH
environment variable frequently defines the locations of classes. Essential classes are loaded first and then application-specific classes are loaded as needed. The JVM frequently uses multiple class loaders. For example, the Sun JVM uses a hierarchy of class loaders:
$JAVAHOME/jre/rt.jar
which contain the standard JDK classes $JAVAHOME/jre/lib/ext/*.jar
The boot class loader loads core classes such as those found in java.lang
and java.util
packages. The JVM command line argument, bootclasspath can be used to direct the JVM to load additional classes.
The extension class loader is concerned with additional classes such as those used in cryptography. It will load files from the $JAVAHOME/jre/lib/ext/
directory and any found in the java.ext.dirs
system property.
The system class loader, also called the application class loader, loads the application classes as specified by the CLASSPATH
environment variable or a Class-Path entry in a JAR file.
Application server-specific class loaders are used by the JVM when the JVM starts up. In the case of the Java EE server, an application server class loader then starts loading classes as specified by the environment variable, $APP_SERVER_HOME/lib
.
As mentioned before, the actual loading process is vendor-specific. However, frequently an EJB class loader is used by an application to load its classes. This loader is often the parent of a WAR class loader. This arrangement results in the classes loaded by the EJB class loader being visible to those loaded by the WAR class loader.
When a class loader loads classes, it does so from a code source location. These locations are dependent on the module. The following table details these locations by module.
Type |
Code source |
---|---|
EAR |
JAR file in its |
Those JARs specified in the Class-Path manifest element of the above JAR files | |
EJB-JAR |
Those in the EJB-JAR file |
Those JARs specified in the Class-Path manifest element of the above EJB-JAR file | |
Those JARs specified in the Class-Path manifest element of the above JAR files | |
WAR |
WEB-INF/classes |
JARs in the | |
Those JARs specified in the Class-Path manifest element of WAR | |
Those JARs specified in the Class-Path manifest element of the above two JAR categories |
Session and message-driven beans are normally packaged in an EJB-JAR file. Entities can also be packaged there. There are several ways of packaging classes into a JAR.
One approach uses the jar
command, which is executed at a command prompt. Most development environments perform this task automatically, hiding the details of this process. The Apache Ant tool or Maven tool is often used for this purpose.
Helper classes contain functionality that can be useful to one or several classes. The visibility of these helper classes can be controlled. To make them visible to all of the application's modules, package them in the EAR's lib directory. To restrict access to them, place the classes in a separate JAR file and add a Class-Path attribute referencing the helper class JAR file in those modules requiring access to them. The Class-Path attribute is found in the containing EJB-JAR or WAR module's Manifest.mf
file. However, when a top level JAR file is processed by a deployment tool it should not contain a Class-Path entry.
3.143.203.96