Chapter 3. Class Loading and Modules

3.1. Introduction

3.1.1. Overview of Class Loading and Modules

JBoss EAP 6 uses a new modular class loading system for controlling the class paths of deployed applications. This system provides more flexibility and control than the traditional system of hierarchical class loaders. Developers have fine-grained control of the classes available to their applications, and can configure a deployment to ignore classes provided by the application server in favour of their own.
The modular class loader separates all Java classes into logical groups called modules. Each module can define dependencies on other modules in order to have the classes from that module added to its own class path. Because each deployed JAR and WAR file is treated as a module, developers can control the contents of their application's class path by adding module configuration to their application.
The following material covers what developers need to know to successfully build and deploy applications on JBoss EAP 6.

3.1.2. Class Loading

Class Loading is the mechanism by which Java classes and resources are loaded into the Java Runtime Environment.

3.1.3. Modules

A Module is a logical grouping of classes used for class loading and dependency management. JBoss EAP 6 identifies two different types of modules, sometimes called static and dynamic modules. However the only difference between the two is how they are packaged. All modules provide the same features.
Static Modules
Static Modules are predefined in the EAP_HOME/modules/ directory of the application server. Each sub-directory represents one module and contains one or more JAR files and a configuration file (module.xml). The name of the module is defined in the module.xml file. All the application server provided APIs are provided as static modules, including the Java EE APIs as well as other APIs such as JBoss Logging.

Example 3.1. Example module.xml file

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
  <resources>
    <resource-root path="mysql-connector-java-5.1.15.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
    <module name="javax.transaction.api"/>
  </dependencies>
</module>

The module name, com.mysql, should match the directory structure for the module.
Creating custom static modules can be useful if many applications are deployed on the same server that use the same third party libraries. Instead of bundling those libraries with each application, a module containing these libraries can be created and installed by the JBoss administrator. The applications can then declare an explicit dependency on the custom static modules.
Dynamic Modules
Dynamic Modules are created and loaded by the application server for each JAR or WAR deployment (or subdeployment in an EAR). The name of a dynamic module is derived from the name of the deployed archive. Because deployments are loaded as modules, they can configure dependencies and be used as dependencies by other deployments.
Modules are only loaded when required. This usually only occurs when an application is deployed that has explicit or implicit dependencies.

3.1.4. Module Dependencies

A module dependency is a declaration that one module requires the classes of another module in order to function. Modules can declare dependencies on any number of other modules. When the application server loads a module, the modular class loader parses the dependencies of that module and adds the classes from each dependency to its class path. If a specified dependency cannot be found, the module will fail to load.
Deployed applications (JAR and WAR) are loaded as dynamic modules and make use of dependencies to access the APIs provided by JBoss EAP 6.
There are two types of dependencies: explicit and implicit.
Explicit dependencies are declared in configuration by the developer. Static modules can declare dependencies in the modules.xml file. Dynamic modules can have dependencies declared in the MANIFEST.MF or jboss-deployment-structure.xml deployment descriptors of the deployment.
Explicit dependencies can be specified as optional. Failure to load an optional dependency will not cause a module to fail to load. However if the dependency becomes available later it will NOT be added to the module's class path. Dependencies must be available when the module is loaded.
Implicit dependencies are added automatically by the application server when certain conditions or meta-data are found in a deployment. The Java EE 6 APIs supplied with JBoss EAP 6 are examples of modules that are added by detection of implicit dependencies in deployments.
Deployments can also be configured to exclude specific implicit dependencies. This is done with the jboss-deployment-structure.xml deployment descriptor file. This is commonly done when an application bundles a specific version of a library that the application server will attempt to add as an implicit dependency.
A module's class path contains only its own classes and that of it's immediate dependencies. A module is not able to access the classes of the dependencies of one of its dependencies. However a module can specify that an explicit dependency is exported. An exported dependency is provided to any module that depends on the module that exports it.

Example 3.2. Module dependencies

Module A depends on Module B and Module B depends on Module C. Module A can access the classes of Module B, and Module B can access the classes of Module C. Module A cannot access the classes of Module C unless:
  • Module A declares an explicit dependency on Module C, or
  • Module B exports its dependency on Module C.

3.1.5. Class Loading in Deployments

For the purposes of classloading all deployments are treated as modules by JBoss EAP 6. These are called dynamic modules. Class loading behavior varies according to the deployment type.
WAR Deployment
A WAR deployment is considered to be a single module. Classes in the WEB-INF/lib directory are treated the same as classes in WEB-INF/classes directory. All classes packaged in the war will be loaded with the same class loader.
EAR Deployment
EAR deployments are made up more than one module. The definition of these modules follows these rules:
  1. The lib/ directory of the EAR is a single module called the parent module.
  2. Each WAR deployment within the EAR is a single module.
  3. Each EJB JAR deployment within the EAR is a single module.
Subdeployment modules (the WAR and JAR deployments within the EAR) have an automatic dependency on the parent module. However they do not have automatic dependencies on each other. This is called subdeployment isolation and can be disabled on a per deployment basis or for the entire application server.
Explicit dependencies between subdeployment modules can be added by the same means as any other module.

3.1.6. Class Loading Precedence

The JBoss EAP 6 modular class loader uses a precedence system to prevent class loading conflicts.
During deployment a complete list of packages and classes is created for each deployment and each of its dependencies. The list is ordered according to the class loading precedence rules. When loading classes at runtime, the class loader searches this list, and loads the first match. This prevents multiple copies of the same classes and packages within the deployments class path from conflicting with each other.
The class loader loads classes in the following order, from highest to lowest:
  1. Implicit dependencies.
    These are the dependencies that are added automatically by JBoss EAP 6, such as the JAVA EE APIs. These dependencies have the highest class loader precedence because they contain common functionality and APIs that are supplied by JBoss EAP 6.
    Refer to Section 3.7.1, “Implicit Module Dependencies” for complete details about each implicit dependency.
  2. Explicit dependencies.
    These are dependencies that are manually added in the application configuration. This can be done using the application's MANIFEST.MF file or the new optional JBoss deployment descriptor jboss-deployment-structure.xml file.
    Refer to Section 3.2, “Add an Explicit Module Dependency to a Deployment” to learn how to add explicit dependencies.
  3. Local resources.
    Class files packaged up inside the deployment itself, e.g. from the WEB-INF/classes or WEB-INF/lib directories of a WAR file.
  4. Inter-deployment dependencies.
    These are dependencies on other deployments in a EAR deployment. This can include classes in the lib directory of the EAR or classes defined in other EJB jars.

3.1.7. Dynamic Module Naming

All deployments are loaded as modules by JBoss EAP 6 and named according to the following conventions.
  1. Deployments of WAR and JAR files are named with the following format:
     deployment.DEPLOYMENT_NAME 
    For example, inventory.war and store.jar will have the module names of deployment.inventory.war and deployment.store.jar respectively.
  2. Subdeployments within an Enterprise Archive are named with the following format:
     deployment.EAR_NAME.SUBDEPLOYMENT_NAME 
    For example, the subdeployment of reports.war within the enterprise archive accounts.ear will have the module name of deployment.accounts.ear.reports.war.

3.1.8. jboss-deployment-structure.xml

jboss-deployment-structure.xml is a new optional deployment descriptor for JBoss EAP 6. This deployment descriptor provides control over class loading in the deployment.
The XML schema for this deployment descriptor is in EAP_HOME/docs/schema/jboss-deployment-structure-1_2.xsd