Oracle8i Java Developer's Guide Release 3 (8.1.7) Part Number A83728-01 |
Library | Service | Contents | Index

## Class.forName() on JServer

The Java Language Specification provides the following description of `Class.forName()`:

  Given the fully-qualified name of a class, this method attempts to locate, load, and link the class. If it succeeds, a reference to the Class object for the class is returned. If it fails, a `ClassNotFoundException` is thrown.

Class lookup is always on behalf of a referencing class through a ClassLoader. The difference between the JDK implementation and JServer's implementation is the method on which the class is found:

- The JDK uses one ClassLoader that searches the set of directory tree roots specified by the environment variable `CLASSPATH`.

- JServer defines several resolvers, which define how to locate classes. Every class has a resolver associated with it, and each class can, potentially, have a different resolver. When you execute a method that calls `Class.forName()`, the resolver of the currently executing class (`this`) is used to locate the class. See "Resolving Class Dependencies" for more information on resolvers.

You can receive unexpected results if you try to locate a class with an unexpected resolver. For example, if a class X in schema X requests a class Y in schema Y to look up class Z, you can experience an error if you expected class X's resolver to be used. Because class Y is performing the lookup, the resolver associated with class Y is used to locate class Z. In summary, if the class exists in another schema and you specified different resolvers for different classes--as would happen by default if they are in different schemas-- you might not find the class.

You can solve this resolver problem as follows:

- Avoid any class name lookup by passing the Class object itself.

- Supply the `ClassLoader` in the `Class.forName` method.

- Supply the class and the schema it resides in to JServer's `classForNameAndSchema` method.

- Supply the schema and class name to `ClassForName.lookupClass`.

- Serialize your objects with the schema name with the class name.

  Note: Another unexpected behavior can occur if system classes invoke `Class.forName()`. The desired class is only found if it resides in SYS or in PUBLIC. If your class does not exist in either SYS or PUBLIC, you can declare a PUBLIC synonym for the class.

### Supply the ClassLoader in Class.forName

JServer uses resolvers for locating classes within schemas. Every class has a specified resolver associated with it. Each class can have a different resolver associated with it. Thus, the locating of classes is dependent on the definition of the associated resolver. The ClassLoader knows which resolver to use based upon the class specified. When you supply a ClassLoader to `Class.forName()`, your class is looked up in the schemas defined within the resolver of the class. The syntax for this variant of `Class.forName` is as follows:

    Class forName (String name, boolean initialize, ClassLoader loader);

The following examples show how to supply the class loader of either the current class instance or the calling class instance.

#### Example 2-3 Retrieve Resolver from Current Class

You can retrieve the class loader of any instance through the `Class.getClassLoader` method. The following example retrieves the class loader of the class represented by instance `x`.

    Class c1 = Class.forName (x.whatClass(), true, x.getClass().getClassLoader());

#### Example 2-4 Retrieve Resolver from Calling Class

You can retrieve the class of the instance that invoked the executing method through the `oracle.aurora.vm.OracleRuntime.getCallerClass` method. Once you retrieve the class, invoke the `Class.getClassLoader` method on the returned class. The following example retrieves the class of the instance that invoked the `workForCaller` method. Then, its class loader is retrieved and supplied to the `Class.forName` method. Thus, the resolver used for looking up the class is the resolver of the calling class.

    void workForCaller() {

    ClassLoader c1 =

    	oracle.aurora.vm.OracleRuntime.getCallerClass().getClassLoader();
    ...
    Class c = Class.forName (name, true, c1);

### Supply Class and Schema Names to classForNameAndSchema

You can resolve the problem of where to find the class by either supplying the resolver, which knows the schemas to search, or by supplying the schema in which the class is loaded. If you know in which schema the class is loaded, you can use the `classForNameAndSchema` method. JServer provides a method in the DbmsJava class, which takes in both the name of the class and the schema that the class resides in. This method locates the class within the designated schema.

#### Example 2-5 Providing Schema and Class Names

The following example shows how you can save the schema and class names in the `save` method. Both names are retrieved and the class is located using the `DbmsJava.classForNameAndSchema` method.

    import oracle.aurora.rdbms.ClassHandle;
    import oracle.aurora.rdbms.Schema;
    import oracle.aurora.rdbms.DbmsJava;

    void save (Class c1) {

    ClassHandle handle = ClassHandle.lookup(c1);
    Schema schema = handle.schema();
    writeNmae (schema.getName());
    writeName (c1.getName());

         }

    Class restore() {

    String schemaName = readName();
    String className = readName();
    return DbmsJava.classForNameAndSchema (schemaName, className);

         }

### Supply Class and Schema Names to lookupClass

You can supply a single String, containing both the schema and class names, to the `oracle.aurora.util.ClassForName.lookupClass` method. When invoked, this method locates the class in the specified schema. The string must be in the following format:

    "<schema>:<class>"

For example, to locate `com.package.myclass` in schema SCOTT, you would execute the following:

    oracle.aurora.util.ClassForName.lookupClass("SCOTT:com.package.myclass");

Note: You must uppercase the schema name. In this case, the schema name is case-sensitive.

### Supply Class and Schema Names when Serializing

When you de-serialize a class, part of the operation is to lookup a class based on a name. In order to ensure that the lookup is successful, the serialized object must contain both the class and schema names.

JServer provides the following classes for serializing and deserializing objects:

- `oracle.aurora.rdbms.DbmsObjectOutputStream`

This class extends `java.io.ObjectOutputStream` and adds schema names in the appropriate places.

- `oracle.aurora.rdbms.DbmsObjectInputStream`

This class extends `java.io.ObjectInputStream` and reads streams written by `DbmsObjectOutputStream`. This class can be used on any environment. If used within JServer, the schema names are read out and used when performing the class lookup. If used on a client, the schema names are ignored.

### Class.forName Example

The following example shows several methods for looking up a class.

- To use the resolver of this instance's class, invoke `lookupWithClassLoader`. This method supplies a class loader to the `Class.forName` method in the `from` variable. The class loader specified in the `from` variable defaults to this class.

- To use the resolver from a specific class, call `ForName` with the designated class name followed by `lookupWithClassLoader`. The `ForName` method sets the `from` variable to the specified class. The `lookupWithClassLoader` method uses the class loader from the specified class.

- To use the resolver from the calling class, invoke the `ForName` method without any parameters. It sets the `from` variable to the calling class. Then, invoke the `lookupWithClassLoader` to locate the class using the resolver of the calling class.

- To lookup a class in a specified schema, invoke the `lookupWithSchema` method. This provides the class and schema name to the `classForNameAndSchema` method.

      import oracle.aurora.vm.OracleRuntime;
      import oracle.aurora.rdbms.Schema;
      import oracle.aurora.rdbms.DbmsJava;

      public class ForName {

        private Class from;
        /* Supply an explicit class to the constructor */
        public ForName(Class from) {
          this.from = from;
        }
        /* Use the class of the code containing the "new ForName()" */
        public ForName() {
          from = OracleRuntime.getCallerClass();
        }

        /* lookup relative to Class supplied to constructor */
        public Class lookupWithClassLoader(String name) throws ClassNotFoundException
      {
          /* A ClassLoader uses the resolver associated with the class*/
          return Class.forName(name, true, from.getClassLoader());
        }

        /* In case the schema containing the class is known */
        static Class lookupWithSchema(String name, String schema) {
          Schema s = Schema.lookup(schema);
          return DbmsJava.classForNameAndSchema(name, s);
        }
      }

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index