Skip Headers
Oracle® Containers for J2EE Developer's Guide
10g (10.1.3.1.0)

Part Number B28952-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

3 Utilizing the OC4J Class Loading Framework

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

The following topics are included:

Class Loading in OC4J

This section contains the following topics:

Overview of 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 class loaders, subclasses of the java.lang.ClassLoader class, which find and load class files at runtime. Class loaders provide an abstraction that enables the JVM to load classes without any knowledge of where the class bytes come from, for both local and remote storage as well as dynamic class generation.

Each class loader works with one or more code sources, root locations from which the class loader 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 class loaders are linked together in a parent-child hierarchy, with each class loader having an associated parent class loader. This hierarchy represents a tree structure, ranging in complexity from simple chains to complex, multibranched trees.

In this hierarchy, a child class loader imports a set of class loaders 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 class loader created at the application level imports a set of class loaders from the system.root class loader.

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

Class Versioning with Shared Libraries in OC4J

The class loader 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 nondefault version of a library or class is needed by an application or module. The OC4J class loading infrastructure addresses this problem by enabling class loaders created for an application or module to import a different version of a shared library than the default imported by the parent class loader, or even remove a class loader from the set of inherited class loaders entirely.

Figure 3-1 illustrates the class loader tree structure in OC4J.

Figure 3-1 The OC4J Class Loader Tree

Description of Figure 3-1 follows
Description of "Figure 3-1 The OC4J Class Loader Tree"

  • 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 class loader 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 class loaders each contain Web module - classes packaged within a WAR file.

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

The OC4J shared class loaders, 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 these items:

  • 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

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

Class Loaders are created at runtime based on the shared library definitions within the OC4J instance. Class Loaders 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 class loaders 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.

Shared Libraries That Applications Import by Default

The default set of shared libraries imported by all application class loaders within the OC4J instance is specified within the <imported-shared-libraries> element in ORACLE_HOME/j2ee/instance/system-application.xml. This is the configuration file for the system application, an internal component of Oracle Containers for J2EE that sits at the root of the application hierarchy and provides classes and configuration required at OC4J startup.

By default, an application deployed to an OC4J instance will inherit these Oracle shared libraries:

  • 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 Nondefault 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, which is an earlier version of the Oracle JDBC driver than the version packaged with OC4J 10g (10.1.3.1.0). This example applies only to thin JDBC drivers and does not apply to the Oracle Call Interface (OCI) drivers.

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 illustrates 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 class loader. 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 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. Uncheck 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 Instead 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 and then force the application to use it instead of the Oracle XML parser or JDBC driver installed with OC4J, without having to declare the JAR as a shared library within OC4J.

Configuring an Application to Use Its Own Shared Library

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 class loader 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 uncomment the <web-app-class-loader> element in this file. Next, set the search-local-classes-first attribute to true in this element, which causes the class loader to find and load any libraries packaged in the WAR and to use these libraries rather than the corresponding libraries packaged with OC4J.

See "Specifying search-local-classes-first at Deployment Time", which follows, 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.

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, using the 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 reuse.

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 composing 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 You Should 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/instance/shared-lib directory and make the required entry in server.xml.

  • Oracle Enterprise Manager 10g Application Server Control Console

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

  • The publishSharedLibrary Ant task

    Enables you to install a shared library on a standalone OC4J server or on a single OC4J instance in an Oracle Application Server environment managed by Oracle Process Manager and Notification Server (OPMN) .

  • The -publishSharedLibrary command in admin_client.jar

    Also enables 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".


Note:

If you are using JDK1.4, Oracle Application Server 10.1.3 does not support using the Xalan library shipped with the JDK as a shared library. To use the Xalan library, you have two alternatives:
  • Use JDK 1.5 (JDK 5), in which the embedded Xalan library is supported as a shared library.

  • With JDK1.4, use a standalone distribution of the Xalan library instead of the embedded version.


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

Shared libraries are installed in the ORACLE_HOME/j2ee/instance/shared-lib directory in OC4J. The process includes creating the correct directory structure within this directory and then copying one or more JAR or ZIP files that compose the library into the directory.

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/instance/shared-lib
  /library_name
    /version
      filename.jar
      filename.zip
      ...

The variables in the directory structure have these values:

  • instance is the name of an OC4J instance, which is home by default in an Oracle Application Server environment and always home on a standalone OC4J server.

  • 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.

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

Given the preceding examples, the resulting directory structure within the OC4J server would be as follows:

ORACLE_HOME/j2ee/instance/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 the following example illustrates:

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

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

  • 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 or ZIP 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 example illustrates a shared library definition in the server.xml configuration file for the example shared library. The code source paths are relative to the subdirectory containing the JAR or ZIP files within the /shared-lib/acme.common directory; therefore, only the archive file names are specified as path values.

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

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. An imported shared library must also be installed and published on the OC4J host.

The following sample code 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 preceding sample entries would resolve to these paths:

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

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 enable you to specify 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 or ZIP file within a shared library. This is the standard J2EE mechanism for declaring dependencies on installed libraries.

To use this mechanism, the dependent JAR or ZIP 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 value specified for the JAR or ZIP file's manifest file:

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 Web site:

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 applications deployed to OC4J, any shared libraries that default 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/instance/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 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 or ZIP files to be shared are installed in the ORACLE_HOME/j2ee/instance/applib directory, is still supported in the current release of OC4J. All JAR and ZIP files within this directory will be included in the global.libraries shared library, and will be available to all applications within the OC4J instance.

Support for this legacy functionality will be removed in a future release of OC4J. Oracle recommends that you use the new shared-library mechanism documented in this chapter whenever possible.

Specifying a Library Directory in application.xml

The <library-directory> element of the application.xml file specifies either a relative or absolute path or URL to a directory or a JAR or ZIP archive to add as a library path for this OC4J instance. Directories are scanned for archives to include at OC4J startup.

If the application.xml file for an application has the version="5" attribute set (JavaEE 5 application), the <library-directory> element of the .ear file's deployment descriptor can contain the name of a library directory through with application components can share libraries.

<application version="5">
    <library-directory>app2lib</library-directory>
    <module>
        <ejb>ejb.jar</ejb>
    </module></application>

If a <library-directory> element is not specified, or if the .ear file does not contain a deployment descriptor, the directory named lib is used.

You can use an empty <library-directory> element to specify that there is no library directory. For example:

<application version="5">
    <library-directory></library-directory>
    <module>
        <ejb>ejb.jar</ejb>
    </module></application>

The <library-directory> element provides a standard mechanism to define class path dependencies, as defined in the JavaEE 5 specification. In OC4j 10g (10.1.3.1.0), all files in a library directory with a .jar extension (but not in subdirectories) are available to all components packaged in the EAR file except application clients. Libraries in these JAR files can reference other libraries, either bundled with the application or installed separately.

OC4j 10g (10.1.3.1.0) also supports the <library-directory> element in J2EE 1.4 applications, with the following caveats:

The proprietary <library> element in the orion-application.xml file provides the same functionality as <library-directory>.

Applications that use the <library-directory> element or JavaEE 5 applications that do not use an empty <library-directory> element will have an extra deployment step that iterates over files in the library directory and adds them to the class path.

Best Practices for Class Loading

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 Class Loader

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

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, which is the search path across a set of loaders and the code sources they contain (for example, JAR files, ZIP files, and directories).

In JavaSE, the class path is usually thought of as the list of code sources specified on the command line or in the manifest file for the main JAR file. 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 JAR files in the jre/lib/ext directory) and the JRE bootstrap loader (containing rt.jar and so on)

The idea that there is a class path is often misleading. For each class lookup, the search begins at a specific loader, and (normally) can visit only loaders above the class. 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 application 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 3-1 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

Class Loader 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> JAR files, ZIP files, and directories in orion-application.xml


<library-directory> JAR files, ZIP files, and directories in application.xml


<ejb> JAR files and ZIP files in orion-application.xml


RAR file: all JAR and ZIP files at the root.


RAR file: <native-library> directory paths


Manifest class path of preceding JAR and ZIP files

app-name.web.web-mod-name

WAR file: Manifest class path


WAR file: WEB-INF/ classes


WAR file: WEB-INF/lib/ all JAR and ZIP files


<classpath> all JAR files, ZIP files, and directories in orion-web.xml


Manifest class path of preceding JAR files


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


Shared libraries are inherited from the application root.


Class Loading 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() and toString() methods with information to help you 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.

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 will always choose 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 nonexistent 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 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 repackaged 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 class loading 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 Class Loader Queries

The following built-in queries are provided with OC4J to assist in troubleshooting class loading 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:

AuditLoader

Performs various diagnostics on the contents of one or more specified class loaders or on all shared class loaders. For example, to audit all shared class loaders with detailed output, specify the AuditLoader query as follows:

AuditLoader * -verbose

Arguments: loaderName [loaderName]... [-verbose] [-includeJREClasses]

Table 3-2 AuditLoader Query Arguments

Argument Description

loaderName

The name of a class loader to audit.

To audit all shared class loaders, specify '*' for loaderName.

-verbose

Optional. Specify to output detailed information.

-includeJREClasses

Optional. Specify to include JRE classes.


Callers

Reports all classes that call the specified method(s). The query optionally takes the name of a class loader 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 class loader:

-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-3 Callers Query Arguments

Argument Description

-loaderName

Optional. If specified, all classes visible from the class loader will be checked for the specified methods.

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

signature

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 one or more specified class loaders or for all class loaders if none is specified. For example:

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

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


Note:

The verbose (multiline) output of the PolicyClassLoader.toString() method has been turned off by default in OC4J 10g (10.1.3). Only the loader name and version are now returned.

You can reenable verbose output by setting either of these system properties:

  • -Dclass.load.trace=any value

  • -Dverbose.loader.tostring=true


Table 3-4 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-5 ClassPath Query Arguments

Argument Description

-list

Optional. Include to generate a line-separated, numbered list of code sources.

loaderName

Optional. If specified, the class loader is used as the starting point from which the classpath is computed. Otherwise, the classpath defaults to the internal oc4j class loader, which loads all OC4J system classes.


Dependencies

Reports all dependencies of the specified class.

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

Table 3-6 Dependencies Query Arguments

Argument Description

className

The fully qualified name of the class to report dependencies for.

loaderName

Optional. If specified, the class loader is used as the starting point from which dependencies are determined. Otherwise, the the internal oc4j class loader, 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-7 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 class loader will be checked. Otherwise, all classes visible to all class loaders from the api class loader downwards are checked.


DuplicateClasses

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

Arguments: [-loaderName] [-systemCodeSources]

Table 3-8 DuplicateClasses Query Arguments

Argument Description

-loaderName

Optional. If specified, the class loader is used as the starting point for the code-source search. Otherwise, all classes visible to all class loaders from the api class loader downwards are checked.

-systemCodeSources

Optional. If specified, includes system code sources in the search.


DuplicateCodeSources

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

Arguments: [-digest]

Table 3-9 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-10 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-11 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.


GetResource

Calls getResource() or getResources() on a specified loader and reports the results.

Arguments: resourcePath [loaderName] [-all]

Table 3-12 GetResource Query Arguments

Argument Description

resourcePath

The fully qualified path to the resource.

loaderName

Optional. If specified, the class loader is used as the starting point for the resource search. Otherwise, all classes visible to all class loaders from the api class loader downwards are checked.

-all

If specified, uses getResources(). Otherwise, uses getResource().


HttpSessions

Reports a summary of active HTTP sessions for deployed applications.

Arguments: [details]

Table 3-13 HttpSessions Query Arguments

Argument Description

details

Optional. If specified, lists details of each HTTP session.


LeakedLoaders

Controls detection of class loader leaks and lists results.

Arguments: [activate|list|deactivate]

Table 3-14 LeakedLoaders Query Arguments

Argument Description

activate

Optional. If specified, activates detection of class loader leaks.

list

Optional. If specified, lists results of class loader leak detection.

deactivate

Optional. If specified, deactivates detection of class loader leaks.


ListQueries

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

Arguments: [-l] [queryclass]...

Table 3-15 ListQueries Query Arguments

Argument Description

-l

Optional. If specified, lists full descriptions.

queryclass

Optional. If specified, lists each query with a single-line description. Pass one or more query class name to list only those queries.


LoadClass

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

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

Table 3-16 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 class loader are reported. If not specified, the oc4j class loader is used by default.

-forName

Optional. The class loader method to record attempts for. If not specified, loader.loadClass() is used by default.

-depends

Optional. Specify to force the class loader 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.


LoadedClasses

Lists the names of all loaded classes (if available).

Arguments: None.

LoaderTree

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

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

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

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

-Doc4j.start.query=LoaderTree

Arguments: [rootLoaderName] [-verbose]

Table 3-17 LoaderTree Query Arguments

Argument Description

rootLoaderName

Optional. The root class loader name. If not specified, reports the contents of the JRE's bootstrap class loader tree.

-verbose

Optional. Specify to output detailed information. If not specified, only the names of the class loaders within the tree are reported.


Packages

Lists the package names contained within one or more code sources.

Arguments: [loaderName | codeSourcePath]

Table 3-18 Packages Query Arguments

Argument Description

loaderName

Optional. If specified, only code sources within that class loader are searched.

codeSourcePath

Optional. If specified, searches the code source path. Otherwise, searches all available code sources.


SharedLibraries

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

Arguments: [loaderName]

Table 3-19 SharedLibraries Query Arguments

Argument Description

loaderName

Optional. The name of a class loader. If specified, lists shared libraries imported by the specified class loader. Otherwise, the shared libraries imported by all class loader instances are listed.


SystemProperties

Lists or sets system properties.

Arguments: [<key>=<value>]...

Table 3-20 SystemProperties Query Arguments

Argument Description

<key>=<value>

Optional. The name and value of a system property. If specified, sets the value of the system property. If no key-value pairs are specified, lists the current values of system properties.


ThreadPools

Lists information about application-server-related thread pools for the current JVM.

Arguments: (list [<sys|req|cx>]|pool [<sys|req|cx>]|state [<sys|req|cx>][<id>)

Table 3-21 ThreadPools Query Arguments

Argument Description

list [<sys|req|cx>]|

If specified, lists all threads in all thread pools or all thread in a specified thread pool.

pool [<sys|req|cx>]|

If specified, lists all thread pools or details for a specified thread pool.

state [<sys|req|cx>][<id>)

If specified, dumps thread state for all thread pools, for a specified thread pool, or for a specified thread ID.


Threads

Lists thread information for the current JVM. For JDK 1.5, checks for thread deadlocks or gets thread memory usage for the current JVM.

Arguments: [list|groups|deadlock|memory]

Table 3-22 Threads Query Arguments

Argument Description

list

Optional. If specified, lists all threads for the current JVM.

groups

Optional. If specified, lists all thread groups for the current JVM.

deadlocks

Optional, for JDK 1.5 only. If specified, checks for thread deadlocks in the current JVM.

memory

Optional, for JDK 1.5 only. If specified, gets thread memory usage for the current JVM.


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

VMStat

Lists statistics information for the current JVM.

Arguments: [jps|pid|mem]

Table 3-23 VMStat Query Arguments

Argument Description

jps

Optional. If specified, Lists the running Java processes.

pid

Optional. If specified, returns the PID of the current JVM.

mem

Optional. If specified, returns memory information about the current JVM.


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 Class Loader 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 Through 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, class loader 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 follows:

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

  • <event> is the event to trace. See Table 3-24 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-24 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 class loader. The object is then cached for subsequent use by class loaders.

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 class loaders 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 class loader.

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

code-source-destroy

Trace events where a code source object is being destroyed.

loader

Trace all class loader lifecycle events.

loader-create

Trace class loader object instantiation events.

loader-commit

Trace events where a class loader object has been created and populated with classes from code sources.

loader-finalize

Trace events where the finalize() method has been called on a class loader 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-25 describes the supported event filter types.

Table 3-25 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.*
    
    
  • Class loader match

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

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

    -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 class loader 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 class loaders:

    -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 Class Loader Log Levels

By default, the class loader 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-26 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, such as to WARNING, to prevent these messages from being filtered from the Logger output.

Table 3-26 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. 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.