Skip Headers
Oracle® Containers for J2EE Developer's Guide
10g Release 3 (10.1.3)
Part No. B14433-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

3 Utilizing the OC4J Class Loading Framework

This chapter provides guidelines on understanding and using the new class loading framework provided in OC4J. Discussions on common classloader problems and recommendations for avoiding them are also provided.

The following topics are included:

Class Loading in OC4J

This section contains the following topics:

What Is Class Loading?

The term class loading refers to the process of locating the bytes for a given class name and converting them into a Java class instance. All class instances within a Java Virtual Machine (JVM) start as an array of bytes, structured in the class file format defined by the JVM specification.

Class loading is performed by the JVM during the startup process, and subsequently by classloaders, subclasses of the java.lang.ClassLoader class that find and load class files at runtime. Classloaders provide an abstraction that allows the JVM to load classes without any knowledge of where the class bytes come from, to enable both local and remote storage as well as dynamic class generation.

Each classloader works with one or more code sources - root locations from which the classloader searches for classes. Code sources can be defined to represent physical storage of binary class files, Java sources that must first be compiled or even classes generated on the fly.

Standard classloaders are linked together in a parent-child hierarchy, with each classloader having an associated parent classloader. This hierarchy represents a tree structure, ranging in complexity from simple chains to complex multi-branched trees.

In this hierarchy, a child classloader imports a set of classloaders from its parent loader. In the OC4J context, all J2EE applications running within an OC4J instance are children of the system application. As a result, a classloader created at the application level imports a set of classloaders from the system.root classloader.

See Figure 3-1 below for a graphical representation of the classloader tree structure used in OC4J.

Class Versioning with Shared Libraries in OC4J

The classloader hierarchy ensures that a J2EE application deployed into the OC4J instance inherits a set of libraries by default from the default application. A Web module bound to this application, in turn, inherits a set of classes from the application, as well as the classes inherited from the system application, which sits at the root of application hierarchy in OC4J.

However, this inheritance model is not always desirable, such as when a non-default version of a library or class is needed by an application or module. The OC4J class loading infrastructure addresses this problem by enabling classloaders created for an application or module to import a different version of a shared library than the default imported by the parent classloader, or even remove a classloader from the set of inherited classloaders entirely.

Figure 3-1 below illustrates the classloader tree structure in OC4J.

Figure 3-1 The OC4J Classloader Tree

Description of jidev001.gif follows
Description of the illustration jidev001.gif

  • The jre.bootstrap loader is a proxy for the native bootstrap loader built into the JVM. The native bootstrap loader itself is not directly visible at runtime.

  • The jre.extension loader is a custom replacement for the JRE-supplied ÒextensionÓ loader.

  • The api loader contains J2EE and OC4J API classes that must be visible to all applications as well as to all OC4J internal classes.

  • The oc4j loader contains OC4J system classes.

  • The system.root loader is created for the OC4J system application.

    Because system is at the root of the application hierarchy, the classes in this loader are inherited by default by all other applications deployed into the OC4J instance.

  • global.root is the classloader created for the default application, which is the default parent of all J2EE applications deployed to the OC4J instance.

  • <app-name>.root is the root loader for a deployed application.

  • app-name.web.web-mod-name classloaders each contain Web module - classes packaged within a WAR file.

  • app-name.jsp.jsp name loads a compiled JSP implementation class.

The OC4J shared classloaders - oracle.jdbc:10.1.0_2, oracle.jdbc:9.2.0_5, oracle:xml:10_1_02 and xerces:xml:2.6.2 - represent shared libraries declared in the OC4J instance. Each shared library definition consists of:

  • A shared library name, such as xerces.xml;

  • A version number that typically represents the shared library's implementation version, such as 2.6.2; and

  • One or more code sources - JAR or ZIP files - containing the classes that comprise the library.

Classloaders are created at runtime based on the shared library definitions within the OC4J instance. Classloaders are registered using a concatenation of the shared library name and the version number; for example, xerces.xml:2.6.2.

See "Installing and Publishing a Shared Library in OC4J" for detailed instructions on creating and installing shared libraries.

Note how JDBC driver and XML parser classes are loaded by the three deployed applications: While Application 1 follows the default behavior of inheriting the classes contained in the oracle.jdbc:10_1_02 and oracle:xml:10_1_02 shared loaders from its parent, Application 2 and Application 3 each import alternative driver and parser classloaders for their use.

By default, an application inherits the same set of shared libraries present in its parent application, including libraries inherited from the system application. This means, for example, that an application will by default use the Oracle JDBC driver and Oracle XML parser, which are inherited from the system application.

However, using OC4J's class versioning capabilities, you can override an inherited library with a different version, or even remove a library from the list of inherited libraries altogether.

What Shared Libraries Do Applications Import by Default?

The default set of shared libraries imported by all application classloaders within the OC4J instance is specified within the imported-shared-libraries element in ORACLE_HOME/j2ee/home/system-application.xml. This is the configuration file for the system application, which is the parent of all applications within the OC4J instance.

The following are the key Oracle shared libraries that an application deployed to an OC4J instance will inherit by default:

  • oracle.jdbc:10.1.0_2

  • oracle.xml:10.1.0_2

  • oracle.cache:10.1.3

  • oracle.http.client:10.1.3

  • oracle.sqlj:10.1.3

  • soap:10.1.3

  • oracle.jwsdl:10.1.3

Configuring an Application to Import a Non-Default Version of a Shared Library

You can force an application to import a different version of a shared library than the one declared in system-application.xml by creating a shared library with the same name, but assigning a different version number. You will then configure the application to import this shared library.

See the following sections for details:

Example: Importing an Earlier Version of the Oracle JDBC Driver

The following example shows you how to configure an application to use an Oracle 9.2.0_5 JDBC driver, an earlier version of the Oracle JDBC driver than the version packaged with OC4J.

Step 1: Create the Shared Library in OC4J

You can install a shared library for the 9.2.x JDBC driver using any of the mechanisms described in "Options for Installing and Publishing a Shared Library". This example will illustrate this task using Application Server Control Console.


Note:

To use a JDBC driver that is not packaged with OC4J, you must create a managed data source specifically for use by the application, then configure the application to use it.

This is necessary because the default JDBC drivers and data sources used by applications are imported by the global system application's classloader. Because your application is loading a different driver, it must also load a data source for the driver to use.

See the Oracle Containers for J2EE Services Guide for details on creating and using application-specific managed data sources.


  1. Click Administration>Shared Libraries. Note the default JDBC driver shared library, oracle.jdbc:10.1.0_2.

  2. Click Create on the Shared Libraries page.

  3. Enter the name for the shared library. In this case, you will enter the same name as the existing library, which is oracle.jdbc.

  4. Enter the shared library version, which in this case is 9.2.0_5.

  5. Click Add to upload the library JAR file to the OC4J instance. The following shared library declaration is added to the ORACLE_HOME/j2ee/instance/server.xml file:

    <shared-library name="oracle.jdbc" version="9.2.0_5">
      		<code-source path="ojdbc14.jar"/>
    	</shared-library>
    

Step 2: Configure an Application to Use the Shared Library

Once the shared library has been created in OC4J, you can configure an application to use it instead of the default shared library installed with OC4J.

The following example illustrates how to do this at the time the application is deployed using Application Server Control Console.

  1. Select Applications>Deploy to launch the Application Server Control Console deployment wizard.

  2. Supply the path to the application in the first page of the wizard.

  3. Specify the application name and supply any context URI mappings in the second page.

  4. Click Configure Class Loading in the third page of the wizard (Deploy: Deployment Settings).

  5. Note that both versions of the oracle.jdbc shared library are listed in the Import Shared Libraries frame. Specify the version number you want to use—9.2.0_5—in the Maximum Version To Use column.

  6. Deploy the application. After the application is deployed, notethe following entry in the application's orion-application.xml file:

    <imported-shared-libraries>
      <import-shared-library name="oracle.jdbc" max-version="9.2.0_05"/>
    </imported-shared-libraries>
    

Example: Configuring an Application to Use a DataDirect JDBC Driver

The Oracle Application Server distribution includes several JDBC drivers to provide connectivity to non-Oracle databases. The following example shows you how to configure an application to use the DataDirect Sybase driver to connect to a Sybase database.

Step 1: Create the Shared Library in OC4J

You can install a shared library for the driver using any of the mechanisms described in "Options for Installing and Publishing a Shared Library". This example will illustrate this task using Application Server Control Console.

  1. Click Administration>Shared Libraries.

  2. Click Create on the Shared Libraries page.

  3. Enter the name for the shared library; for example, sybase.jdbc.

  4. Enter the shared library version, for example: 1.0.

  5. Click Add to upload the library JAR files to the OC4J instance. Note that the YMbase.jar and YMutil.jar files are required to use any of the DataDirect drivers provided with Oracle Application Server.

    • YMsybase.jar

    • YMbase.jar

    • YMutil.jar

    The following shared library declaration is added to the ORACLE_HOME/j2ee/<instance>/server.xml file:

    <shared-library name="sybase.jdbc" version="1.0">
      		<code-source path="YMbase.jar"/>
      		<code-source path="YMutil.jar"/>
      		<code-source path="YMsybase.jar"/>
    	</shared-library>
    

Step 2: Configure an Application to Use the Shared Library

Once the shared library has been created in OC4J, you can configure an application to use it instead of the default shared library installed with OC4J.

The following example illustrates how to do this at the time the application is deployed using Application Server Control Console.

  1. Select Applications>Deploy to launch the Application Server Control Console deployment wizard.

  2. Supply the path to the application in the first page of the wizard.

  3. Specify the application name and supply any context URI mappings in the second page.

  4. Click Configure Class Loading in the third page of the wizard (Deploy: Deployment Settings).

  5. Check the Import checkbox for the sybase.jdbc shared library. Optionally specify 1.0 as the maximum version to use.

  6. Deploy the application. After the application is deployed, notethe following entry in the application's orion-application.xml file:

    <imported-shared-libraries>
      <import-shared-library name="sybase.jdbc" max-version="1.0"/>
    </imported-shared-libraries>
    

Removing and/or Replacing an Oracle Shared Library Imported by Default

The shared library framework also allows a shared library to be removed from the set of shared libraries inherited by an application from its parent, and optionally allows a different shared library to be imported in its place.

Shared libraries inherited by default can be removed using one or more <remove-inherited> subelements within an <imported-shared-libraries> in the application's orion-application.xml file. The name of the library to remove is specified as the value for the name attribute.

For example, the following entry in orion-application.xml will prevent the application from importing the Oracle TopLink shared library:

<orion-application>
  <imported-shared-libraries>
    <remove-inherited name="oracle.toplink"/>
  </imported-shared-libraries>
</orion-application>

See the following sections for complete examples:

Example: Replacing the Oracle XML Parser with the Xerces Parser

The following example illustrates how to remove the Oracle XML parser from the default set of shared libraries inherited from the system application using Application Server Control Console. It will also force the application to use the Xerces XML parser in its place.

Step 1: Create the Shared Library in OC4J

You can install a shared library for the Xerces parser using any of the mechanisms described in "Options for Installing and Publishing a Shared Library". This example will illustrate this task using Application Server Control Console.

  1. Click Administration>Shared Libraries.

  2. Click Create on the Shared Libraries page.

  3. Enter the name for the shared library. In this case, you will enter xerces.xml.

  4. Enter the shared library version, which in this case is 2.5.0.

  5. Click Add to upload the library JAR files to the OC4J instance. Upload the following Apache libraries:

    • xercesImpl.jar

    • xml-apis.jar

    The following shared library declaration is added to the ORACLE_HOME/j2ee/<instance>/server.xml file:

    <shared-library name="xerces.mxl" version="2.5.0">
      		<code-source path="xercesImpl.jar"/>
      <code-source path="xml-apis.jar"/>
    	</shared-library>
    

Step 2: Configure an Application to Use the Shared Library

Once the shared library has been created in OC4J, you can configure an application to use the Xerces parser instead of the default parser installed with OC4J.

The following example illustrates how to do this at the time the application is deployed using Application Server Control Console.

  1. Select Applications>Deploy to launch the Application Server Control Console deployment wizard.

  2. Supply the path to the application in the first page of the wizard.

  3. Specify the application name and supply any context URI mappings in the second page.

  4. Click Configure Class Loading in the third page of the wizard (Deploy: Deployment Settings).

  5. Check the Import checkbox for the xerces.xml shared library. Optionally specify 2.5.0 as the maximum version to use.

  6. To explicitly remove the Oracle parser, un-check the Import checkbox for the oracle.xml shared library to remove it from the list of shared libraries inherited by the application.

  7. Optionally click the Save Deployment Plan button, and save the plan for re-use.

  8. Deploy the application. After the application is deployed, note the following entry in the application's orion-application.xml file:

    <orion-application>
      <imported-shared-libraries>
        <remove-inherited name="oracle.xml"/>
        <import-shared-library name="xerces.xml" max-version="2.5.0/>
      </imported-shared-libraries>
    </orion-application>
    

Example: Removing an Oracle Shared Library at Deployment Time

The following example illustrates how to remove the Oracle TopLink shared library at the time the application is deployed using Application Server Control Console.

  1. Select Applications>Deploy to launch the Application Server Control Console deployment wizard.

  2. Supply the path to the application in the first page of the wizard.

  3. Specify the application name and supply any context URI mappings in the second page.

  4. Click Configure Class Loading in the third page of the wizard (Deploy: Deployment Settings).

  5. Un-check the Import checkbox for the oracle.toplink shared library to remove it from the list of shared libraries inherited by the application.

  6. Optionally click the Save Deployment Plan button, and save the plan for re-use.

  7. Deploy the application. After the application is deployed, note the following entry in the application's orion-application.xml file:

    <orion-application>
      <imported-shared-libraries>
        <remove-inherited name="oracle.toplink"/>
      </imported-shared-libraries>
    </orion-application>
    

Using a Packaged JAR In Place of an Oracle Shared Library

The class loading infrastructure enables you to package an XML parser or JDBC driver as a JAR with your application, then force the application to use it in place of the Oracle XML parser or JDBC driver installed with OC4J—without having to declare the JAR as a shared library within OC4J.

In this case, you will specify the default inherited Oracle library in the <remove-inherited> tag in orion-application.xml, which is then packaged with the JAR in the application's EAR file. After deployment into OC4J, the application will not import the default library installed with OC4J, causing the application's classloader to find and load your packaged library instead.

The following notation in orion-application.xml will prevent the application's class loader from importing the Oracle XML parser:

<imported-shared-libraries>
  <remove-inherited name="oracle.xml"/>
</imported-shared-libraries>

In the case of Web applications, you can specify that classes bundled within the application's WAR file be used through a notation in the application's orion-web.xml descriptor file.

First, add or un-comment the <web-app-class-loader> element in this file. Next, set the search-local-classes-first attribute to true in this element will cause the classloader to find and load any libraries packaged in the WAR, and use these rather than corresponding libraries packaged with OC4J.

See "Example: Specifying search-local-classes-first at Deployment Time" below for details on how you can do this at deployment time using Application Server Control Console.

The entry in orion-web.xml looks like this:

<orion-web-app ...>
  ...
  <web-app-class-loader search-local-classes-first="true"
   include-war-manifest-class-path="true" />
  ...
</orion-web-app>

Note that this approach is not a guaranteed solution; if an application further up the hierarchy imports a shared library that includes the same classes, a collision is likely— and such collisions are difficult to debug. Ideally, you should use the shared library mechanism documented in this chapter to ensure that your Web applications use the correct library.

Example: Specifying search-local-classes-first at Deployment Time

The following example illustrates how to set the search-local-classes-first attribute in the orion-web.xml file generated for the Web module at deployment time. this at the time the application is deployed using Application Server Control Console.

  1. Select Applications>Deploy to launch the Application Server Control Console deployment wizard.

  2. Supply the path to the application in the first page of the wizard.

  3. Specify the application name and supply any context URI mappings in the second page.

  4. Click Configure Class Loading in the third page of the wizard (Deploy: Deployment Settings).

  5. Under Configure Web Module Class Loaders, check the Search Local Classes First checkbox next to the name of the Web module containing the local JAR file to use.

  6. Optionally click the Save Deployment Plan button, and save the plan for re-use.

Installing and Publishing a Shared Library in OC4J

Creating a shared library within an OC4J instance is essentially a two-step process. First, the binaries comprising the shared library must be installed in the appropriate directory within OC4J. The shared library must then be declared in the OC4J server configuration file (server.xml), essentially "publishing" it within the OC4J instance.

This section includes the following topics:

When Should You Use a Shared Library?

Typically, applications deployed into OC4J will use the set of shared libraries packaged with OC4J, which are inherited from the system application. However, there are scenarios in which replacing or removing a library inherited from the application's parent is necessary. Example use cases include:

  • Using a different version of the Oracle JDBC driver then the version packaged with OC4J

  • Replacing the Oracle XML parser packaged with OC4J with a different parser for use by your application

  • Sharing proprietary classes across one or more specific applications, rather than across all applications

  • Making an open source library, such as Struts or the Spring Framework, available to multiple Web applications

Options for Installing and Publishing a Shared Library

OC4J provides several options for installing and publishing shared libraries within one or more OC4J instances. Each of these mechanisms will install the shared library in the ORACLE_HOME/j2ee/home/shared-lib directory and make the required entry in server.xml.

  • Oracle Enterprise Manager 10g Application Server Control Console

    Allows you to install a shared library on a specific OC4J instance through the Administration>Administration Tasks>Shared Libraries pages.

  • The publishSharedLibrary Ant task

    Allows you to install a shared library on a single OPMN-managed OC4J instance or on a standalone OC4J server.

  • The -publishSharedLibrary command in admin_client.jar

    Also allows you to install a shared library on a single OPMN-managed OC4J instance or on a standalone OC4J server.

You can also manually install and publish a shared library within an OC4J instance following the process outlined in the next section, "How a Shared Library is Installed and Published in an OC4J Instance".

How a Shared Library is Installed and Published in an OC4J Instance

Shared libraries are installed in the ORACLE_HOME/j2ee/home/shared-lib directory in OC4J. The process includes creating the correct directory structure within this directory, then copying the JAR files that comprise the library into it.

OC4J provides several tools that automate this process. See "Options for Installing and Publishing a Shared Library" for an overview.

First, the following directory structure for the library is created within this directory:

ORACLE_HOME/j2ee/home/shared-lib
  /library_name
    /version
      filename.jar
      filenamejar
      ...

  • library_name is a directory named with the name of the shared library; for example, "acme.common".

    In cases where common APIs are implemented by multiple vendors, the name should include both the vendor name and the name of the technology; for example, oracle.jdbc or xerces.xml. If the technology is implemented by a single vendor, the technology name alone is sufficient.

  • version is a subdirectory named for the shared library version number; for example "2.5". This value should ideally reflect the code implementation version.

Once these directories have been created, copy each JAR or ZIP file containing the classes that comprise the shared library into the version subdirectory. For example, assume the sample library consists of acme-apis.jar and acmeImpl.jar.

Given the examples above, the resulting directory structure within the OC4J server would be:

ORACLE_HOME/j2ee/home/shared-lib
  /acme.common
    /2.5
      acme-apis.jar
      acmeImpl.jar

Multiple versions of the shared library are installed by creating a new subdirectory for each version's archive files within this directory structure, as illustrated below:

ORACLE_HOME/j2ee/home/shared-lib
  /acme.common
    /2.5
      acme-apis.jar
      acmeImpl.jar
    /3.0
      acme-apis.jar
      acmeImpl.jar

Once the code sources are installed, the shared library is defined within a <shared-library> element that is added to the ORACLE_HOME/j2ee/home/server.xml file, which contains the configuration data for the OC4J instance. The <shared-library> element takes the following:

  • A required name attribute, the value of which must match the name of the shared library directory created within the /shared-lib directory.

  • A required version attribute, the value of which must match the version number that serves as the name of the subdirectory containing the shared library's archive files in the /shared-lib/library_name directory.

  • One or more <code-source> subelements, each containing a path attribute defining the path to a JAR or ZIP file belonging to the library.

    Paths may be absolute if outside of the /shared-lib directory, or can be relative to the subdirectory containing the JAR files within the /shared-lib/library_name directory. If relative, only the archive file name needs to be supplied as the value for path.

The following illustrates a shared library definition in the server.xml configuration file for the example shared library. Note that the code source paths are relative to the subdirectory containing the JAR files within the /shared-lib/acme.common directory; therefore, only the archive file names are specified as the value for path.

<shared-library name=Óacme.commonÓ version=Ó2.5Ó>
  <code-source path=Óacme-apis.jarÓ/>
  <code-source path=ÓacmeImpl.jarÓ/>
</shared-library>

Note that you can optionally set path="*" to force OC4J to consume all of the archives within the subdirectory. For example:

<shared-library name=Óacme.commonÓ version=Ó2.5Ó>
  <code-source path="*" />
</shared-library>

Additionally, a shared library can be configured to import one or more other shared libraries. The <shared-library> element can optionally take one or more <import-shared-library> elements, each specifying a shared library to be imported by the shared library being configured. Note that an imported shared library must also be installed and published on the OC4J host.

The following example causes the acme.common shared library to import the xyz.log shared library:

<shared-library name=Óacme.commonÓ version=Ó2.5Ó>
  <import-shared-library name="xyz.log"/>
  <code-source path=Óacme-apis.jarÓ/>
  <code-source path=ÓacmeImpl.jarÓ/>
</shared-library>

When a relative code source path is encountered at runtime, the full path is constructed by concatenating the shared library directory (/shared-lib), the shared library name and the version number. For example, the sample entries above would resolve to:

ORACLE_HOME/j2ee/home/shared-lib/acme.common/2.5/acme-apis.jar
ORACLE_HOME/j2ee/home/shared-lib/acme.common/2.5/acmeImpl.ja

Configuring an Application to Import a Shared Library

Once a shared library is installed, you can configure applications to import it using one of the following options:


Note:

Declaring a dependency using any of these options makes the shared library required by the application. An error will result if the shared library has not already been installed and published within the OC4J instance.

Declaring Dependencies in an Application's OC4J Deployment Descriptor

A dependency can be declared by adding notations in the dependent application's orion-application.xml deployment descriptor.

Dependencies are declared by adding an <imported-shared-libraries> element in the application-specific orion-application.xml configuration file. This element takes one or more <import-shared-library> subelements, each specifying a shared library to import.

The <import-shared-library> element has the following attributes:

  • name: The name of the shared library.

  • min-version and max-version: These are optional attributes that allow a minimum or maximum version of the library to be specified for inclusion. To use the latest installed version of the library, do not specify a version number.

The following entry in orion-application.xml will import the acme.common:2.5 shared library for use by the application:

<imported-shared-libraries>
  <import-shared-library name="acme.common" max-version="2.6"/>
</imported-shared-libraries>

Declaring Dependencies in an Application's Manifest File

The standard Java extension mechanism - also known as optional packages - can be utilized to declare an application dependency on a JAR file within a shared library. This is the standard J2EE mechanism for declaring dependencies on installed libraries.

To use this mechanism, the dependent JAR file must be declared as a named extension in its MANIFEST.MF file. This name is specified as the value of the Extension-Name attribute. For example, the following manifest entry defines acme.common as an extension:

Extension-Name: acme.common
Specification-Vendor: Acme, Inc 
Specification-Version: 2.5 
Implementation-Vendor-Id: com.acme 
Implementation-Vendor: Acme, Inc 
Implementation-Version: 2.5 

The application that is dependent on the shared library then declares the dependency in its own manifest file. The following manifest attributes will cause the application to import the acme.common:2.5 shared library. Note that the value of the name-Extension-Name attribute exactly matches the Extension-Name specified in the JAR file's manifest:

Extension-List: acme
acme-Extension-Name: acme.common
acme-Implementation-Version: 2.5

For more information on declaring dependencies using manifest files, see the following link:

http://java.sun.com/j2se/1.4.2/docs/guide/extensions/versioning.html

Configuring All Deployed Applications to Import a Specific Shared Library

You can ensure that all applications deployed to an OC4J instance use the same version of a shared library by configuring the default application to import it. Because default is the parent of all other applications deployed to OC4J, any shared libraries it imports will also be imported by these applications.

The configuration is managed by adding the XML notations described in "Declaring Dependencies in an Application's OC4J Deployment Descriptor" to the ORACLE_HOME/j2ee/home/application.xml file, the configuration file for the default application.

The following entry in application.xml will ensure that all deployed applications use version 2.0 of the acme.common shared library:

<imported-shared-libraries>
  <import-shared-library name="acme.common" max-version="2.0"/>
</imported-shared-libraries>

Note that an application will use the version of a shared library imported from the default application—even if the application includes its own version of the shared library. If this is not desirable, you can "remove" the version imported from default using the process described in "Removing and/or Replacing an Oracle Shared Library Imported by Default".

Sharing Libraries Using the /applib Directory

The legacy mechanism for sharing libraries across applications within OC4J, in which JAR files to be shared are installed in the ORACLE_HOME/j2ee/home/applib directory, is still supported in the current release of OC4J. All JAR files within this directory will be included in the global.libraries shared library, and will be available to all applications within the OC4J instance.

Be advised that support for this legacy functionality will be removed in a future release of OC4J. You are strongly encouraged to use the new shared library mechanism documented in this chapter whenever possible.

Class Loading Best Practices

This section provides guidelines for avoiding class loading issues.

Declare Class Dependencies

Make dependencies explicit in the application's MANIFEST.MF file or orion-application.xml file. Hidden or unknown dependencies will be left behind when you move your application to another environment.

Group Dependencies Together

Ensure that all dependencies are visible at the same level or above. If you must move a library, make sure all dependencies are still visible. Ensure that application resources, dependent third-party libraries and other enterprise modules are packaged in a self-contained manner.

Share Rather Than Duplicate Libraries

Avoid duplicating libraries, which increases both the disk and memory footprints and can lead to version problems.

Minimize Library Visibility

Dependency libraries should be placed at the lowest visibility level that satisfies all dependencies.

Keep Your Configurations Portable

Choose configuration options in the following order:

  1. Standard J2EE options

  2. Options that can be expressed within your EAR file

  3. Server-level options

  4. J2SE extension options

Be Sure to Use the Correct Classloader

If you use reflection by calling Class.forName(), always explicitly pass the classloader returned by Thread.currentThread().getContextClassLoader. If you are loading a properties file, use Thread.currentThread().getContextClassLoader().getResourceAsStream().

Troubleshooting Class Loading-Related Problems in OC4J

OC4J provides features to help you troubleshoot class loading-related issues.

Overview of Troubleshooting

Most class loading errors in Java are related to visibility—either not enough or, more rarely, too much. Visibility in this case refers to the set of classes and resources that are available on the "class-path": the search path across a set of loaders and the code-sources (e.g. JARs and/or directories) they contain.

In JavaSE, the class-path is usually thought of as the list of code-sources specified on the command-line or in the manifest Class-Path of the main jar. These code-sources are all deployed in a single loader, usually referred to as the "system" loader. This loader is in turn wired up to two other loaders: the JRE extensions loader (normally for any JARs in the jre/lib/ext directory) and the JRE bootstrap loader (containing rt.jar etc.)

The idea that there is a class-path is often quite misleading. For each class lookup, the search begins at a specific loader, and (normally) can only visit loaders "above" it. This means that a search starting at the extensions loader would have a very different class-path than one starting at the system loader.

In JavaEE, the situation is substantially more complicated, as multiple class loaders are required in place of the single system loader. Each deployed application has at least one loader, separate from all other applications, so each has a distinct class-path. There are frequently different class-paths even within a single application, as each web module is deployed in a separate loader.

This can easily be seen by making the following call from within different modules, as OC4J ensures that the correct class-path is returned for the calling module:

System.getProperty("java.class.path");

There are many configuration options that affect class visibility for applications. Table (UNKNOWN STEP NUMBER) lists the most common options within OC4J. Given the possible combinations of loaders and code-sources in a JavaEE environment, it is easy to see how visibility errors can arise. Often, a simple configuration change is all that is required to eliminate the problem, but understanding what change to make can be tricky.

Table 3-1 Configuration Options Affecting Class Visibility

Classloader Configuration Option
Configured shared library <code-source> in server.xml

<import-shared-library> in server.xml
app-name.root <import-shared-library> in orion-application.xml

<library> jars/directories in orion-application.xml

<ejb> JARs in orion-application.xml

RAR file: all JARs at the root.

RAR file: <native-library> directory paths.

Manifest Class-Path of above JARs
app-name.web.web-mod-name WAR file: Manifest Class-Path

WAR file: WEB-INF/classes

WAR file: WEB-INF/lib/ all JARs

<classpath> jars/directories in orion-web.xml

Manifest Class-Path of above jars.

search-local-classes-first attribute in orion-web.xml

Shared libraries are inherited from the app root.

Classloader-Related Errors and Exceptions

Most class loading errors in J2EE often surface as one of a small set of exceptions. The OC4J class-loading infrastructure provides "annotated" subclasses for each of the following standard class-loading configuration exceptions:

The subclasses enhance the output of the getMessage(), printStackTrace() or toString() methods with information to help understand and correct the configuration. Often, this extra information is all that is needed to fix the problem; when it isn't, the logging, tracing and query features can be used to dig further.

For each error, a diagnostic search may be performed to provide additional information. This search is not restricted by standard loader visibility rules, and can visit any loader or code-source known to the system. Results are reported as part of the error message.

Note that under some conditions it would be possible for the loader runtime to act on the results and attempt recovery (such as automatically find and load a missing class). However, this might lead to further problems that would then be more difficult to diagnose.

ClassNotFoundException

This exception can occur during dynamic loading via any method that explicitly loads a class by name, such as Class.forName() or ClassLoader.loadClass(). It indicates that a required class is not visible from the initiating class loader.

How to troubleshoot and resolve

ClassNotFoundException is nearly identical to NoClassDefFoundError. One important difference is that the initial loader can be selected by the calling code, rather than by the JVM, and it is relatively easy to get this wrong.

If the Class.forName(String) method is used, the JRE code will select the initial loader, and always chooses the caller's loader. This is rarely correct - it is nearly always better to explicitly pass the thread context loader:

Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
Class cls = loader.loadClass(name);

Note that calling the loader directly is preferred to using the Class.forName() variant:

Class cls = Class.forName(name, true, loader);

While these two calls both try to load from the specified loader, the direct call is easier to understand. It also ensures that tracing works as expected, since some VM implementations of forName() can bypass the loader (only calling the loader if the class is not already cached—the loader always consults the cache itself, so calling the loader directly is safe and efficient).

The LoadClass query can be useful to experiment with loading classes from different initial loaders.

If the correct initial loader was used, then a code-source is likely missing in the search path. See "NoClassDefFoundError" for more detail.

NoClassDefFoundError

This exception can occur when the VM attempts to resolve a static dependency from one class to another. It is a type of LinkageError that indicates that the required class is not visible from the initiating loader. Since static dependency resolution is often deferred until first use, this error can occur at unexpected times.

Example Error Message

Missing class: acme.Dynamite

	Dependent class: acme.RoadRunner
Loader: acme.root:0.0.0
Code-Source: /myapps/acme/acme.jar
Configuration: <ejb> in /myapps/acme/application.xml

The missing class is available from the following locations:

1.	Code-Source: /shared/bang/0.0.0/bang.jar (from <code-source> 
in j2ee/home/server.xml)

This code-source is available in loader bang:0.0.0. This 
shared-library can be imported by the "acme" application.

How to troubleshoot and resolve

Examine the error message. The first line names the missing class. The next four lines describe the class that has the dependency: its name, the loader that defined it (also the "initiating" loader, selected by the VM), the code-source from which it came, and the configuration option that caused the code-source to be added to that loader. Subsequent lines describe the result of the diagnostic search, and will likely provide enough detail to resolve the issue.

Some common conditions reported by the diagnostic search are listed below, each with specific suggestions for resolution:

  • The missing class is not present in any code-source visible to the system.

    This often simply means that another code-source must be added (which in turn may require others). Use the dependent class information to choose the right level at which to add the configuration, and then select a convenient option (see Table 3-1, "Configuration Options Affecting Class Visibility"). Consider creating a new shared-library if other applications are likely to need the same classes. Note that once created, the new shared-library must also be imported.

    This result can also mean that an existing code source declaration is invalid. When a path is encountered that does not point to a valid file or directory, this fact is logged, but at a level that is normally masked. To see all messages, start the system with the following setting:

    -Dclass.load.log.level=finest

    Look for messages about "non-existent" code-sources, find the relevant one and correct the configuration. There are often may of these messages, so it may be helpful to direct the output to a file (for example, "loader.log") that can be more easily searched:

    -Dclass.load.log.file=loader.log

  • The missing class is present in a shared library, but that shared library was not imported.

    Import the shared library, either through Application Server Control Console or by adding an <import-shared-library> element to the application.

  • The missing class is present, but the loader configured to use it is a child of the initiating loader.

    This most often occurs when a class deployed in an application root loader (for example, an EJB) has a dependency on a class deployed in a Web module. Resolving requires either refactoring to eliminate the dependency or moving the classes into the same loader. Often, the simplest solution is to move such classes from the Web module up to the application root, but the reverse may also be possible. See Table 3-1, "Configuration Options Affecting Class Visibility" for options to add code-sources to the root.

    Note that copying rather than moving such classes can lead to a ClassCastException when the search-local-classes-first option in the web module is enabled.

  • The missing class is present, but the loader configured to use it is in an unrelated application.

    An ideal solution in this case is to move the relevant code-sources out of the existing application into a new shared library and reconfigure both applications to import it. When this is not practical, the code-source may be copied into the current application. While it is possible to use configuration to point directly at the code-source in the other application, this will cause failures if that application is ever undeployed.

    The ClassPath query can be useful to examine code-source search order from a specific loader:

    -Doc4j.start.query="ClassPath(acme.root)+Exit"

    The SharedLibraries query may also be used to list all shared libraries and the loaders that import them.

ClassFormatError

This error can occur when a class is first loaded (during definition). It is a type of LinkageError, and often indicates that the class was compiled for a different version of the JVM.

How to troubleshoot and resolve

The error message will specify the version with which the class was compiled, and the version supported by the current runtime.

To correct the failure, either switch to the correct version of JVM, or re-compile the class for the current one.

LinkageError

This error can occur when a class is first loaded (during definition). The more common LinkageError subtypes are processed as special cases by the OC4J class loading system (see NoClassDefFoundError and ClassFormatError) -- the remaining cases generally indicate one of the following:

  • A mismatch between the versions of a class used at compile time and that found at runtime

  • A native library is required but cannot be found.

How to troubleshoot and resolve

The error message will specify the actual failure, and will also provide the name, defining loader, code-source and configuration for two different classes: the one that failed during definition, and the class that has the dependency that caused the definition to occur.

If the message indicates a version mismatch of some sort, such as NoSuchMethodError, source level changes and re-compilation will be required to resolve the failure. Frequently, the mismatch occurs between a superclass or interface and a subclass, and should be relatively easy to discern.

An UnsatisfiedLinkError means that a native library could not be found. Generally, OC4J only supports configuring native libraries within RAR modules (see Table Table 3-1, "Configuration Options Affecting Class Visibility" ). If the library is specified within a RAR, it may be an invalid path. See "NoClassDefFoundError" for a discussion of using the class.load.log.level property to detect this case.

ClassCastException

This exception usually occurs for obvious reasons, such as:

Object source = new Integer(0);
String target = (String) source; // Exception

However, this exception can also be class loading related. Unfortunately the error message created by the VM is normally empty, and even when this exception is loading related, it cannot be intercepted and annotated.

When more than one loader defines a class with the same name, a cast between the two types will fail with a ClassCastException:

import com.acme.Foo;
...
// Get the loader that resolves our static dependency
// on class Foo

ClassLoader expected = Foo.class.getClassLoader();

// Dynamically load Foo from another loader and
// create an instance

Class fooClass = aLoader.loadClass("com.acme.Foo");
Object source = fooClass.newInstance();
ClassLoader actual = fooClass.getClassLoader();

// Compare and cast

System.out.println(actual == expected); // "false"
Foo target = (Foo) source; // Exception


In this case, the loader instances are different, and so the JVM considers the two classes to be unrelated.

A relatively common example of this problem happens within a single application, when an EJB interface is packaged both in the ejb-module, and in a web-module that uses the EJB. If the search-local-classes-first option is enabled for the web-module, the EJB classes will be loaded twice.

How to troubleshoot and resolve

First, determine the target type of the cast by looking at the code described at the top of the stack trace. If the cast is to a primitive type (such as int or long) or to a class defined by the JRE (for example, String, HashMap, or any other java.* class), then it is almost certainly not class loading related and is a (usually simple) developer error.

Next, use tracing to see definition(s) of the target class. For example, if the target of the cast is com.acme.Foo, use:

-Dclass.load.trace=class-defined:com.acme.Foo

The output will describe the loader and the code-source from which the class is defined. If there is only one, then the problem is unlikely to be class loading related (though it is still possible if custom class loaders are in use, as they won't participate in tracing).

If there is more than one definition of the target class, then it is very likely that they are coming into contact and causing the exception. If the trace messages list the same code-source for both definitions, then it is being shared across loaders and should be easy to re-arrange.

However, it is far more common that the code-sources will be different, perhaps because classes were re-packaged for convenience (nearly always a bad idea), or because they are different versions. If one of the loaders is from a web module, disabling search-local-classes-first may be sufficient.

If the code can be instrumented, duplication can be confirmed by adding code just before the cast (where obj is the object being cast):

ClassLoader expected = Foo.class.getClassLoader();
System.out.println("Expected: " + expected);
ClassLoader actual = obj.getClass().getClassLoader();
System.out.println("  Actual: " + actual);

The output should agree with the loaders named in the tracing messages. Note that if obj is a subclass of the expected type, then walking the hierarchy with Class.getSupertype() may be required.

If duplication is confirmed as the cause, it must be eliminated. This can be accomplished by arranging for the class to be shared: either move the class to a common parent of the two loaders or to a shared-library. To help determine which loader should continue to load the class, it may be helpful to see the call stack at the point of each class definition:

-Dclass.load.trace=class-defined:com.acme.Foo+stack

It may also be useful to see the relationships between loaders using the LoaderTree query:

-Doc4j.start.query=LoaderTree

Queries can also be executed on a running instance using the ASControl system MBean browser. The -verbose option can be used with this query to see lots of detail:

-Doc4j.start.query="LoaderTree(-verbose)+Exit"

The DuplicateClasses query can also be used to search for potential duplicates (same class names in different code-sources).

Using Queries to Troubleshoot Class Loading Issues

OC4J provides a number of built-in queries that can be run to troubleshoot classloader-related problems. Queries can be executed at OC4J startup by setting the oc4j.start.query system property, or at runtime through the ClassLoading MBean.


Note:

This feature is subject to change in future releases of OC4J.

Summary of Available Queries

The following built-in queries are provided with OC4J to assist in troubleshooting class loading-related problems.

Note that the examples used illustrate usage of the oc4j.start.query system property, which is set on the oc4j.jar command line at OC4J startup.

The available queries are as follows:

Callers

Reports all classes that call the specified method(s). The query optionally takes the name of a classloader to limit the query to.

For example, to find all classes that call System.currentTimeMillis(), execute the following:

-Doc4j.start.query=Callers(java.lang.System.currentTimeMillis()long)

The next example will find the same method in classes visible from the MyApp.root classloader:

-Doc4j.start.query=Callers(-MyApp.root,java.lang.System.currentTimeMillis()long)

To find calls to either version of the overloaded Class.forName() method, pass in both method signatures as arguments:

-Doc4j.start.query=Callers(java.lang.Class.forName(java.lang.
String)java.lang.Class,java.lang.Class.forName(java.lang.String;boolean;java.lang.
ClassLoader)java.lang.Class)

Note that you can include "<init>" in the <signature> argument to specify a constructor:

-Doc4j.start.query=Callers(java.util.Date.<init>())

Arguments: [-<loaderName> <signature>...

Table 3-2 Callers Query Arguments

Argument Description
-loaderName Optional. If specified, all classes visible from the classloader will be checked for the specified methods.

If not specified, all classes visible to all classloaders down the tree from the api classloader - the default parent of all application-specific classloaders - are checked.

signature Required. A method to check for. Multiple methods may be specified, each as a separate argument.

The syntax is:

class-type.method-name[parameter-type]*)return-type

Separate multiple parameter types using semicolons (;). Types must be either fully qualified class names or primitive names. For void return types, the return-type may be omitted.


ClassLoadMetrics

Reports metrics for the specified classloader(s), or for all classloaders if none are specified. For example:

-Doc4j.start.query=ClassLoadMetrics(MyApp.root,MyOtherApp.root)

Arguments: [-verbose] [<loaderName>]...

Table 3-3 ClassLoadMetrics Query Arguments

Argument Description
-verbose Optional. Supply to generate detailed metrics.
loaderName Optional. The name(s) of the class loader(s) to report metrics for.

ClassPath

Reports the code-sources in use.

Arguments:[-list] [loaderName]

Table 3-4 ClassPath Query Arguments

Argument Description
-list Optional. Include to generate a line-separated, numbered list of code-sources.
loaderName Optional. If specified, the classloader is used as the starting point from which the classpath is computed. Otherwise, the classpath defaults to the internal oc4j classloader, which loads all OC4J system classes.

Dependencies

Reports all dependencies of the specified class.

Arguments: <className> [loaderName] [-r]

Table 3-5 Dependencies Query Arguments

Argument Description
className The fully qualified name of the class to report dependencies for.
loaderName Optional. If specified, the classloader is used as the starting point from which depedencies are determined. Otherwise, the the internal oc4j classloader, which loads system classes, is used.
-r Optional. Set to search classes recursively. Note that use of this option can cause long execution times.

Depends

Reports on all classes that are dependent on the specified class.

Arguments: [-loaderName] <className>

Table 3-6 Depends Query Arguments

Argument Description
className The fully qualified name of the class to check for dependencies. To specify an entire package, use an asterisk (*) as the leaf name.
loaderName Optional. If specified, all classes visible to the classloader will be checked. Otherwise, all classes visible to all classloaders from the api classloader downwards are checked.

DuplicateClasses

Reports the existence of classes/resources with the same name in different code sources.

Arguments: None

DuplicateCodeSources

Reports code-sources that have the same name or have more than one subscriber.

Arguments: [-digest]

Table 3-7 DuplicateCodeSources Query Arguments

Argument Description
-digest Optional. If specified, bit-wise comparisons of code-sources will be performed.

Exit

Exits the process and shuts down OC4J if running. This is useful if you only want to execute the query without leaving the OC4J server running. For example:

-Doc4j.start.query=LoaderTree+Exit

Arguments: [-force]

Table 3-8 Exit Query Arguments

Argument Description
-force Optional. Forces a System.exit() call instead of a normal shutdown.

FindResource

Reports the code-sources containing the specified resource, identified either by classname or resource path.

A leading or trailing asterisk * can be used for a simple wildcard search, or a leading ~ may be used to indicate that the argument should be treated as a regular expression.The resourcePath argument must be passed to search for classes with no package. For example, to find class foo, the query would be:

-Doc4j.start.query=FindResource(Foo.class)

To search for resources with no package (/), where the resource name contains a period (.), a leading asterisk must be used. For example, use the following query to find the myconfig.xml file at the root of a code-source:

-Doc4j.start.query=FindResource(*myconfig.xml)

Arguments: [-list] <resourcePath>|<className>

Table 3-9 FindResource Query Arguments

Argument Description
-list Optional. Can be used with wildcard or regular expressions to list all matching resources.
resourcePath The fully qualified path to the resource. Either resourcePath or className must be supplied.
className The fully qualified classname of the resource to search for. Either resourcePath or className must be supplied.

ListQueries

Lists all of the available queries in OC4J, by oracle.oc4j.query.Query subclass name.

Arguments: None

LoadClass

Attempts to load the specified class using the specific classloader, or using the internal oc4j classloader if none specified, and reports the result. The query in effect performs a class loading "test run".

Arguments: <className> [loaderName] [-forName] [-depends] [-r] [-sort]

Table 3-10 LoadClass Query Arguments

Argument Description
className Required. The fully qualified name of the class to report on.
loaderName Optional. If specified, attempts to load the class using this classloader are reported. If not specified, the oc4j classloader is used by default.
-forName Optional. The classloader method to record attempts for. If not specified, loader.loadClass() is used by default.
-depends Optional. Specify to force the classloader to load and report on all dependencies of the specified class.
-r Optional. Specify to load all dependencies recursively. Note that recursion does not include classes in java.* packages.
-sort Optional. Include to sort the list of dependent classes by class name.

LoaderTree

Reports the contents of the classloader tree for the specified root classloader, or for the JRE's bootstrap classloader if none specified. By default, only the names of the classloaders within the tree are reported.

This query is useful if you want to focus on a specific part of the classloader tree, such as from the root of a specific application downwards. For example:

-Doc4j.start.query=LoaderTree(MyApp.root)

To retrieve the entire classloader tree, do not include a root classloader name:

-Doc4j.start.query=LoaderTree

Arguments: [rootLoaderName] [-verbose]

Table 3-11 LoaderTree Query Arguments

Argument Description
rootLoaderName Optional. The root classloader name. If not specified, reports the contents of the JRE's bootstrap classloader tree.
-verbose Optional. Specify to output detailed information. If not specified, only the names of the classloaders within the tree are reported.

SharedLibraries

Lists all installed shared libraries and the class loaders that import each.

Arguments: [loaderName]

Table 3-12 SharedLibraries Query Arguments

Argument Description
loaderName Optional. If specified, lists shared libraries imported by the specified classloader. Otherwise, the shared libraries imported by all classloader instances are listed.

SystemProperties

Reports the contents of the System properties.

Arguments: None

UnusedCodeSources

Reports code-sources that have never retuned any data.

Arguments: None

Uptime

Reports the length of time the current OC4J server instance has been running.

Arguments: None

Executing Queries at OC4J Startup

Queries can be executed at OC4J startup by setting the oc4j.start.query system property on the oc4j.jar command line.

Query results are written to the file specified as the value of the class.load.log.file property, or to the console (System.out) if no file is specified. See "Setting Classloader Log Levels" for details on the class.load.log.file property.

Note that system properties must be prefaced on the command line with a -D. The syntax is as follows:

java -Doc4j.start.query=<queryName>(arg0,arg1,...) -jar oc4j.jar

Arguments can be passed in with the query by appending (arg0,arg1,...)to the query name. Note that arguments are enclosed in parentheses. Multiple arguments are separated by a comma.


Note:

For some UNIX shells, the property value string—everything after the = symbol—will need to be quoted.

For example, the DuplicateCodeSources query can be invoked with a -digest argument as follows:

java -Doc4j.start.query=DuplicateCodeSources(-digest) -jar oc4j.jar

Multiple queries may be specified by separating them with the + character:

-Doc4j.start.query=DuplicateCodeSources(-digest)+UnusedCodeSources

Executing Queries at Runtime via the ClassLoading MBean

Queries can be executed on a running OC4J instance by calling the executeQuery operation on the ClassLoading MBean.

This MBean is accessible through the Web-based Application Server Control Console interface. See the Oracle Containers for J2EE Configuration and Administration Guide for details on accessing and using the MBeans packaged with OC4J.

  1. Click the Administration link in the Application Server Control Console.

  2. Click System MBean Browser.

  3. Expand the ClassLoading node in the navigation pane, then select the singleton MBean instance.

  4. Click the Operations tab in the right-hand pane, then click the executeQuery operation.


    Note:

    Two versions of the executeQuery operation are exposed. Click the version that takes two parameters. (The queryClassData parameter cannot be set through the System MBean Browser.)

  5. Enter the name of the query you want to execute as the value for queryClassName. For example, LoaderTree.

  6. Click the queryArguments icon, then add a new row for each argument you want to specify. Do NOT enclose arguments in parentheses; these are added automatically when the operation is invoked. Click OK when finished specifying arguments.

  7. Click the Invoke button to call the operation.

Tracing Class Loading Events to Help Troubleshoot Issues

OC4J provides the class.load.trace system property that can be set to trace class loading, classloader lifecycle and code-source lifecycle events. The tracing output generated can be extremely useful in troubleshooting class loading-related issues.


Note:

This feature is subject to change in future releases of OC4J.

The class.load.trace property is set at OC4J startup. The syntax is as follows:

class.load.trace=<event>[[:<string-filter>[,<string-filter>]] |
 [~<pattern-filter>]]

  • <event> is the event to trace. See Table 3-13 for valid values.

    Multiple event values can be strung together with a + character.

    -Dclass.load.trace=class+loader 
    
    
  • <string-filter> is a filter applied to manage trace output. Note that a colon (:) separates the initial filter from the event. See "Using Filters to Manage Trace Output" for details on the types of filters that can be applied to manage trace output.

    Multiple filters can be separated by a comma:

    -Dclass.load.trace=class:com.acme.Foo,com.acme.Bar
    
    
  • <pattern-filter> is a single filter that is interpreted as a regular expression. Note that a ~ character precedes the filter.


Notes:

  • System properties must be prefaced on the command line with a -D. For example:

    java -Dclass.load.trace=loader -jar oc4j.jar
    
    
  • In a standalone OC4J configuration, system properties are set directly on the oc4j.jar command line, as shown in the example above.

  • In an Oracle Application Server configuration, system properties are set in the <data> element where the id attribute is "java-options" in the opmn.xml file for the OC4J instance. For example:

    <data id="java-options" value="-Dejb3=true  -Dclass.load.trace=class+loader"/>
    

Trace output is written to the console by default, but can be written to a file specified using the class.load.log.file system property. For example:

java -Dclass.load.log.file=C:\logs\logfile.txt -jar oc4j.jar

Table 3-13 class.load.trace System Property Values

Value Description
all Activate all tracing modes. Note that setting this value may slightly impact OC4J performance, due to the volume of output.
none Disable all tracing modes.
class Trace all class loading search events.
class-defined Trace all events in which the specified class is initially loaded by a classloader. The object is then cached for subsequent use by classloaders.
class-found Trace all search events where the specified class was found.
class-not-found Trace all search events where the specified class was not found.
code-source Trace all code source lifecycle events.
code-source-create Trace events where a code source object is first initialized. Only one instance of a code source is created in memory; this object is then shared by all classloaders that need it.
code-source-dependency Trace events for all code sources where extension dependencies declared in the MANIFEST.MF file packaged within the archive were found or not found.
code-source-dependency-satisfied Trace events for all code sources where all extension dependencies declared in the MANIFEST.MF file packaged within the archive were found.
code-source-dependency-not-satisfied Trace events for all code sources where all extension dependencies declared in the MANIFEST.MF file packaged within the archive were not found.
code-source-manifest Trace events for all code sources where a MANIFEST.MF file is packaged within the archive and any class paths, extension declarations, etc. are being processed.
code-source-state Trace events for two the following code source states:
  • Open: Code source is actively being searched for or used by a classloader.

  • Closed: Code source is not currently being used by a classloader, and is basically in a passivated state.

code-source-destroy Trace events where a code source object is being destroyed.
loader Trace all classloader lifecycle events.
loader-create Trace classloader object instantiation events.
loader-commit Trace events where a classloader object has been created and populated with classes from code sources.
loader-finalize Trace events where the finalize() method has been called on a classloader object and the object is no longer accessible.
loader-close Trace events where a class loader object is in the process of being garbage collected by the JVM.
loader-destroy Trace events where a class loader object is being destroyed.
resource Trace all resource search events.
resource-found Trace all resource search events where the resource was found.
resource-not-found Trace all resource search events where the resource was not found.
stack Add a stack trace to all events.
help or ? Print the help text to the console.

Using Filters to Manage Trace Output

The class.load.trace system property supports the use of filters to make event tracing output more manageable. The syntax is as follows. Note that a colon (:) separates the initial filter from the event to trace:

<event>[[:<string-filter>[,<string-filter>]] | [~<pattern-filter>]]

Table 3-14 describes the supported event filter types.

Table 3-14 Supported Trace Output Filters

Event Supported Filters
class
  • Exact match

    Specify the fully qualified name of the class to trace events for. The following example will only trace loading of the com.acme.Dynamite class:

    -Dclass.load.trace=class:com.acme.Dynamite
    
    
  • Prefix or suffix match

    Use a leading or trailing asterisk (*) to treat the string as a prefix or suffix. For example:

    -Dclass.load.trace=class:com.acme.*
    -Dclass.load.trace=code-source:*foo.jar
    
    
  • Regular expression match

    Use a tilde (~) to treat the string as a regular expression. Note that the .* syntax indicates that any number of characters can match the expression.

    The following example will trace class loading events for class names containing "util":

    -Dclass.load.trace=class~.*util.*
    
    
  • Classloader match

    Begin the filter string with loader. to treat the remainder of the string as a classloader name.

    The following example will trace loading only of classes performed by the api classloader, the default parent of all application-specific classloaders:

    -Dclass.load.trace=class:loader.api
    
    
code-source
  • Full path

    Specify the full path for the code source to trace events for. For example:

    -Dclass.load.trace=code-source:/C:/oc4j/xdk/lib
    
    
  • Partial path

    Use a leading or trailing asterisk (*) to treat the string as a prefix or suffix. This example will trace loading only of classes in the com.acme package:

    -Dclass.load.trace=code-source:*/acme.jar
    -Dclass.load.trace=code-source:/C:/oc4j/*
    
    
  • Regular expression match

    Use a tilde (~) to treat the string as a regular expression. Note that the .* syntax indicates that any number of characters can match the expression.

    The following example will trace code-source-create events for the "foo" application:

    -Dclass.load.trace=code-source-create~.*/foo/.*
    
loader
  • Exact match

    Specify the complete name (name.name:version) of the classloader to trace events for. For example:

    -Dclass.load.trace=loader:oracle.jdbc:10.1.0_2
    
    
  • Suffix match

    Use a trailing asterisk (*) to treat the string as a suffix. For example:

    -Dclass.load.trace=loader:oracle.jdbc:*
    
    
  • Regular expression match

    Use a tilde (~) to treat the string as a regular expression. Note that the .* syntax indicates that any number of characters can match the expression.

    The following example will trace create events for application root classloaders:

    -Dclass.load.trace=loader-create~.*root.*
    
resource
  • Full path

    Specify the full path for the resource. For example:

    -Dclass.load.trace=resource:META-INF/services/
      javax.xml.parsers.DocumentBuilderFactory.
    
    
  • Partial path

    Use a leading or trailing asterisk (*) to treat the string as a prefix or suffix. This example will only trace loading of classes in the com.acme package:

    -Dclass.load.trace=resource:*Messages_en.properties
    -Dclass.load.trace=resource: oracle/oc4j/admin/jmx/model/*
    
    
  • Regular expression match

    Use a tilde (~) to treat the string as a regular expression. Note that the .* syntax indicates that any number of characters can match the expression.

    The following example will trace all resource searches for property files with "security" in the path:

    -Dclass.load.trace=resource~.*security.*properties
    

Setting Classloader Log Levels

By default, the classloader Logger messages are filtered at the CONFIG Java log level. If necessary, you can use the class.load.log.level system property to change the log level. Table 3-15 below lists the values that can be set on this property.

For example, to set the log level to SEVERE:

-Dclass.load.log.level=severe

Note that tracing-related messages are written at the INFO log level. As a result, avoid setting the log level above INFO - to WARNING, for example - to prevent these messages from being filtered from the Logger output.

Table 3-15 class.load.log.level System Property Values

Value Description
all Output all log messages.
severe Output messages at the SEVERE level only.
warning Output messages at the WARNING level or above.
info Output messages at the INFO level or above. Note that if the log level is set below info - for example, to finer - trace output will be filtered from the logger output.
config Output messages at the CONFIG level or above. This is the default log level.
fine Output messages at the FINE level or above.
finer Output messages at the FINER level or above.
finest Output messages at the FINEST level or above.
off Suppress all logging messages.