Returns the canonical instance of the default provider
for the service provider interface
will use the canonical instance of the default provider
as the service provider instance.
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. If
the URLClassLoader
was created by this provider to
service an invocation of its loadClass
or
loadProxyClass
methods, then no permissions are
required to get the associated codebase string. If it is an
arbitrary other URLClassLoader
instance, then if
there is a security manager, its checkPermission
method will be invoked once for each URL returned by the
getURLs
method, with the permission returned by
invoking openConnection().getPermission()
on each
URL; if any of those invocations throws a
SecurityException
or an IOException
,
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.
- 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,
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 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 getClassLoader
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 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
, 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 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.