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

will use the canonical instance of the default provider as the service provider instance.

If there is a security manager, its checkPermission method will be invoked with a RuntimePermission("setFactory") permission; this could result in a SecurityException.

The default service provider instance implements RMIClassLoaderSpi as follows:

The RMIClassLoaderSpi.getClassAnnotation(Class) 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:

For the implementations of the methods described below, which all take a String parameter named codebase that is a space-separated list of URLs, each invocation has an associated codebase loader that is identified using the codebase argument in conjunction with the current thread's context class loader (see Thread.getContextClassLoader()). When there is a security manager, this provider maintains an internal table of class loader instances (which are at least instances of java.net.URLClassLoader) keyed by the pair of their parent class loader and their codebase URL path (an ordered list of URLs). If the codebase argument is null, the codebase URL path is the value of the system property java.rmi.server.codebase or possibly an earlier cached value. For a given codebase URL path passed as the codebase argument to an invocation of one of the below methods in a given context, the codebase loader is the loader in the table with the specified codebase URL path and the current thread's context class loader as its parent. If no such loader exists, then one is created and added to the table. The table does not maintain strong references to its contained loaders, in order to allow them and their defined classes to be garbage collected when not otherwise reachable. In order to prevent arbitrary untrusted code from being implicitly loaded into a virtual machine with no security manager, if there is no security manager set, the codebase loader is just the current thread's context class loader (the supplied codebase URL path is ignored, so remote class loading is disabled).

The RMIClassLoaderSpi.getClassLoader(String) method returns the codebase loader for the specified codebase URL path. If there is a security manager, then if the calling context does not have permission to connect to all of the URLs in the codebase URL path, a SecurityException will be thrown.

The RMIClassLoaderSpi.loadClass(String,String,ClassLoader) 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, such as 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 codebase loader for the specified codebase URL path. If there is a security manager, then the calling context must have permission to connect to all of the URLs in the codebase URL path; otherwise, the current thread's context class loader will be used instead of the codebase loader.

The RMIClassLoaderSpi.loadProxyClass(String,String[],ClassLoader) 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 java.lang.reflect.Proxy.getProxyClass(ClassLoader,Class[])) 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

Exceptions:
SecurityException    if there is a security manager and the invocation of its checkPermission method fails

Since:  1.4