Understanding class loading

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.

Getting ready

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:

  • The loader checks its local cache to see if it is available
  • If not, it asks the parent loader to load the class
  • If the parent cannot load the class it uses a local source such as a JAR file

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.

How to do it...

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.

How it works...

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:

  • Boot class loader Loads classes from $JAVAHOME/jre/rt.jar which contain the standard JDK classes
  • Extension class loader Follows the boot class loader and loads classes from $JAVAHOME/jre/lib/ext/*.jar
  • System class loader Loads application-specific classes

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 /lib directory

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 WEB-INF/lib directory

 

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

 

There's more...

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.203.96