# Class RMIClassLoader

java.lang.Object
java.rmi.server.RMIClassLoader

public class RMIClassLoader extends Object
`RMIClassLoader` comprises static methods to support dynamic class loading with RMI. Included are methods for loading classes from a network location (one or more URLs) and obtaining the location from which an existing class should be loaded by remote parties. These methods are used by the RMI runtime when marshalling and unmarshalling classes contained in the arguments and return values of remote method calls.

The implementation of the following static methods

- `loadClass(URL,String)`
- `loadClass(String,String)`
- `loadClass(String,String,ClassLoader)`
- `loadProxyClass(String,String[],ClassLoader)`
- `getClassLoader(String)`
- `getClassAnnotation(Class)`

is provided by an instance of `RMIClassLoaderSpi`, the service provider interface for those methods. When one of the methods is invoked, its behavior is to delegate to a corresponding method on the service provider instance. The details of how each method delegates to the provider instance is described in the documentation for each particular method.

The service provider instance is chosen as follows:

- If the system property `java.rmi.server.RMIClassLoaderSpi` is defined, then if its value equals the string `"default"`, the provider instance will be the value returned by an invocation of the `getDefaultProviderInstance()` method, and for any other value, if a class named with the value of the property can be loaded by the system class loader (see `ClassLoader.getSystemClassLoader()`) and that class is assignable to `RMIClassLoaderSpi` and has a public no-argument constructor, then that constructor will be invoked to create the provider instance. If the property is defined but any other of those conditions are not true, then an unspecified `Error` will be thrown to code that attempts to use `RMIClassLoader`, indicating the failure to obtain a provider instance.
- If a resource named `META-INF/services/java.rmi.server.RMIClassLoaderSpi` is visible to the system class loader, then the contents of that resource are interpreted as a provider-configuration file, and the first class name specified in that file is used as the provider class name. If a class with that name can be loaded by the system class loader and that class is assignable to `RMIClassLoaderSpi` and has a public no-argument constructor, then that constructor will be invoked to create the provider instance. If the resource is found but a provider cannot be instantiated as described, then an unspecified `Error` will be thrown to code that attempts to use `RMIClassLoader`, indicating the failure to obtain a provider instance.
- Otherwise, the provider instance will be the value returned by an invocation of the `getDefaultProviderInstance()` method.

Since:
  1.1
See Also:
  - `RMIClassLoaderSpi`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static String`
  `getClassAnnotation(Class<?> cl)`
  Returns the annotation string (representing a location for the class definition) that RMI will use to annotate the class descriptor when marshalling objects of the given class.
  `static ClassLoader`
  `getClassLoader(String codebase)`
  Returns a class loader that loads classes from the given codebase URL path.
  `static RMIClassLoaderSpi`
  `getDefaultProviderInstance()`
  Returns the canonical instance of the default provider for the service provider interface `RMIClassLoaderSpi`.
  `static Object`
  `getSecurityContext(ClassLoader loader)`
  Deprecated.
  no replacement.
  `static Class<?>`
  `loadClass(String name)`
  Deprecated.
  replaced by `loadClass(String,String)` method
  `static Class<?>`
  `loadClass(String codebase, String name)`
  Loads a class from a codebase URL path.
  `static Class<?>`
  `loadClass(String codebase, String name, ClassLoader defaultLoader)`
  Loads a class from a codebase URL path, optionally using the supplied loader.
  `static Class<?>`
  `loadClass(URL codebase, String name)`
  Loads a class from a codebase URL.
  `static Class<?>`
  `loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader)`
  Loads a dynamic proxy class (see `Proxy`) that implements a set of interfaces with the given names from a codebase URL path.

  ### Methods declared in class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### loadClass

    @Deprecated public static Class<?> loadClass(String name) throws MalformedURLException, ClassNotFoundException
    Deprecated.
    replaced by `loadClass(String,String)` method
    Loads the class with the specified `name`.

    This method delegates to `loadClass(String,String)`, passing `null` as the first argument and `name` as the second argument.

    Parameters:
      `name` - the name of the class to load
    Returns:
      the `Class` object representing the loaded class
    Throws:
      `MalformedURLException` - if a provider-specific URL used to load classes is invalid
      `ClassNotFoundException` - if a definition for the class could not be found at the codebase location
    See Also:
      - `loadClass(String,String)`

  - ### loadClass

    public static Class<?> loadClass(URL codebase, String name) throws MalformedURLException, ClassNotFoundException
    Loads a class from a codebase URL. If `codebase` is `null`, then this method will behave the same as `loadClass(String,String)` with a `null` `codebase` and the given class name.

    This method delegates to the `RMIClassLoaderSpi.loadClass(String,String,ClassLoader)` method of the provider instance, passing the result of invoking `URL.toString()` on the given URL (or `null` if `codebase` is null) as the first argument, `name` as the second argument, and `null` as the third argument.

    Parameters:
      `codebase` - the URL to load the class from, or `null`
      `name` - the name of the class to load
    Returns:
      the `Class` object representing the loaded class
    Throws:
      `MalformedURLException` - if `codebase` is `null` and a provider-specific URL used to load classes is invalid
      `ClassNotFoundException` - if a definition for the class could not be found at the specified URL

  - ### loadClass

    public static Class<?> loadClass(String codebase, String name) throws MalformedURLException, ClassNotFoundException
    Loads a class from a codebase URL path.

    This method delegates to the `RMIClassLoaderSpi.loadClass(String,String,ClassLoader)` method of the provider instance, passing `codebase` as the first argument, `name` as the second argument, and `null` as the third argument.

    Parameters:
      `codebase` - the list of URLs (separated by spaces) to load the class from, or `null`
      `name` - the name of the class to load
    Returns:
      the `Class` object representing the loaded class
    Throws:
      `MalformedURLException` - if `codebase` is non-`null` and contains an invalid URL, or if `codebase` is `null` and a provider-specific URL used to load classes is invalid
      `ClassNotFoundException` - if a definition for the class could not be found at the specified location
    Since:
      1.2

  - ### loadClass

    public static Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException
    Loads a class from a codebase URL path, optionally using the supplied loader. This method should be used when the caller would like to make available to the provider implementation an additional contextual class loader to consider, such as the loader of a caller on the stack. Typically, a provider implementation will attempt to resolve the named class using the given `defaultLoader`, if specified, before attempting to resolve the class from the codebase URL path.

    This method delegates to the `RMIClassLoaderSpi.loadClass(String,String,ClassLoader)` method of the provider instance, passing `codebase` as the first argument, `name` as the second argument, and `defaultLoader` as the third argument.

    Parameters:
      `codebase` - the list of URLs (separated by spaces) to load the class from, or `null`
      `name` - the name of the class to load
      `defaultLoader` - additional contextual class loader to use, or `null`
    Returns:
      the `Class` object representing the loaded class
    Throws:
      `MalformedURLException` - if `codebase` is non-`null` and contains an invalid URL, or if `codebase` is `null` and a provider-specific URL used to load classes is invalid
      `ClassNotFoundException` - if a definition for the class could not be found at the specified location
    Since:
      1.4

  - ### loadProxyClass

    public static Class<?> loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws ClassNotFoundException, MalformedURLException
    Loads a dynamic proxy class (see `Proxy`) that implements a set of interfaces with the given names from a codebase URL path.

    The interfaces will be resolved similar to classes loaded via the `loadClass(String,String)` method using the given `codebase`.

    This method delegates to the `RMIClassLoaderSpi.loadProxyClass(String,String[],ClassLoader)` method of the provider instance, passing `codebase` as the first argument, `interfaces` as the second argument, and `defaultLoader` as the third argument.

    Parameters:
      `codebase` - the list of URLs (space-separated) to load classes from, or `null`
      `interfaces` - the names of the interfaces for the proxy class to implement
      `defaultLoader` - additional contextual class loader to use, or `null`
    Returns:
      a dynamic proxy class that implements the named interfaces
    Throws:
      `MalformedURLException` - if `codebase` is non-`null` and contains an invalid URL, or if `codebase` is `null` and a provider-specific URL used to load classes is invalid
      `ClassNotFoundException` - if a definition for one of the named interfaces could not be found at the specified location, or if creation of the dynamic proxy class failed (such as if `Proxy.getProxyClass(ClassLoader,Class[])` would throw an `IllegalArgumentException` for the given interface list)
    Since:
      1.4

  - ### getClassLoader

    public static ClassLoader getClassLoader(String codebase) throws MalformedURLException
    Returns a class loader that loads classes from the given codebase URL path.

    The class loader returned is the class loader that the `loadClass(String,String)` method would use to load classes for the same `codebase` argument.

    This method delegates to the `RMIClassLoaderSpi.getClassLoader(String)` method of the provider instance, passing `codebase` as the argument.

    Parameters:
      `codebase` - the list of URLs (space-separated) from which the returned class loader will load classes from, or `null`
    Returns:
      a class loader that loads classes from the given codebase URL path
    Throws:
      `MalformedURLException` - if `codebase` is non-`null` and contains an invalid URL, or if `codebase` is `null` and a provider-specific URL used to identify the class loader is invalid
    Since:
      1.3

  - ### getClassAnnotation

    public static String getClassAnnotation(Class<?> cl)
    Returns the annotation string (representing a location for the class definition) that RMI will use to annotate the class descriptor when marshalling objects of the given class.

    This method delegates to the `RMIClassLoaderSpi.getClassAnnotation(Class)` method of the provider instance, passing `cl` as the argument.

    Parameters:
      `cl` - the class to obtain the annotation for
    Returns:
      a string to be used to annotate the given class when it gets marshalled, or `null`
    Throws:
      `NullPointerException` - if `cl` is `null`
    Since:
      1.2

  - ### getDefaultProviderInstance

    public static RMIClassLoaderSpi getDefaultProviderInstance()
    Returns the canonical instance of the default provider for the service provider interface `RMIClassLoaderSpi`. If the system property `java.rmi.server.RMIClassLoaderSpi` is not defined, then the `RMIClassLoader` static methods
    - `loadClass(URL,String)`
    - `loadClass(String,String)`
    - `loadClass(String,String,ClassLoader)`
    - `loadProxyClass(String,String[],ClassLoader)`
    - `getClassLoader(String)`
    - `getClassAnnotation(Class)`
    will use the canonical instance of the default provider as the service provider instance.

    The default service provider instance implements `RMIClassLoaderSpi` as follows:

    > The `getClassAnnotation` method returns a `String` representing the codebase URL path that a remote party should use to download the definition for the specified class. The format of the returned string is a path of URLs separated by spaces. The codebase string returned depends on the defining class loader of the specified class:

    > - If the class loader is the system class loader (see `ClassLoader.getSystemClassLoader()`), a parent of the system class loader such as the loader used for installed extensions, or the bootstrap class loader (which may be represented by `null`), then the value of the `java.rmi.server.codebase` property (or possibly an earlier cached value) is returned, or `null` is returned if that property is not set.

    > - Otherwise, if the class loader is an instance of `URLClassLoader`, then the returned string is a space-separated list of the external forms of the URLs returned by invoking the `getURLs` methods of the loader.

    > - Finally, if the class loader is not an instance of `URLClassLoader`, then the value of the `java.rmi.server.codebase` property (or possibly an earlier cached value) is returned, or `null` is returned if that property is not set.

    > For the implementations of the methods described below, which all take a `String` parameter named `codebase` that is a space-separated list of URLs, the `codebase` argument is ignored. Class loading proceeds using the the current thread's context class loader (see `Thread.getContextClassLoader()`), which is also considered to be the codebase loader, irrespective of any value passed as the `codebase` argument.

    > The `getClassLoader` method returns the current thread's context class loader.

    > The `loadClass` method attempts to load the class with the specified name as follows:

    > > If the `defaultLoader` argument is non-`null`, it first attempts to load the class with the specified `name` using the `defaultLoader`, as if by evaluating

    > >         Class.forName(name, false, defaultLoader)

    > > If the class is successfully loaded from the `defaultLoader`, that class is returned. If an exception other than `ClassNotFoundException` is thrown, that exception is thrown to the caller.

    > > Next, the `loadClass` method attempts to load the class with the specified `name` using the current thread's context class loader.

    > The `loadProxyClass` method attempts to return a dynamic proxy class with the named interface as follows:

    > > If the `defaultLoader` argument is non-`null` and all of the named interfaces can be resolved through that loader, then,

    > > - if all of the resolved interfaces are `public`, then it first attempts to obtain a dynamic proxy class (using `Proxy.getProxyClass`) for the resolved interfaces defined in the codebase loader; if that attempt throws an `IllegalArgumentException`, it then attempts to obtain a dynamic proxy class for the resolved interfaces defined in the `defaultLoader`. If both attempts throw `IllegalArgumentException`, then this method throws a `ClassNotFoundException`. If any other exception is thrown, that exception is thrown to the caller.
    > > - if all of the non-`public` resolved interfaces are defined in the same class loader, then it attempts to obtain a dynamic proxy class for the resolved interfaces defined in that loader.
    > > - otherwise, a `LinkageError` is thrown (because a class that implements all of the specified interfaces cannot be defined in any loader).

    > > Otherwise, if all of the named interfaces can be resolved through the codebase loader, then,

    > > - if all of the resolved interfaces are `public`, then it attempts to obtain a dynamic proxy class for the resolved interfaces in the codebase loader. If the attempt throws an `IllegalArgumentException`, then this method throws a `ClassNotFoundException`.
    > > - if all of the non-`public` resolved interfaces are defined in the same class loader, then it attempts to obtain a dynamic proxy class for the resolved interfaces defined in that loader.
    > > - otherwise, a `LinkageError` is thrown (because a class that implements all of the specified interfaces cannot be defined in any loader).

    > > Otherwise, a `ClassNotFoundException` is thrown for one of the named interfaces that could not be resolved.

    Returns:
      the canonical instance of the default service provider
    Since:
      1.4

  - ### getSecurityContext

    @Deprecated public static Object getSecurityContext(ClassLoader loader)
    Deprecated.
    no replacement. This method has no purpose in the absence of a Security Manager.
    Always returns null.
    Parameters:
      `loader` - a class loader from which to get the security context
    Returns:
      null