- java.lang.Object
-
- java.rmi.server.RMIClassLoader
-
public class RMIClassLoader extends Object
RMIClassLoader
包含静态方法来支持使用RMI的动态类加载。 包括从网络位置(一个或多个URL)加载类的方法,并获取远程方应由现有类加载的位置。 这些方法由RMI运行时使用,当编组和解组合包含在远程方法调用的参数和返回值中时,它们也可以被应用程序直接调用,以模仿RMI的动态类加载行为。执行以下静态方法
-
loadClass(URL,String)
-
loadClass(String,String)
-
loadClass(String,String,ClassLoader)
-
loadProxyClass(String,String[],ClassLoader)
-
getClassLoader(String)
-
getClassAnnotation(Class)
RMIClassLoaderSpi
的实例提供,这些方法的服务提供程序接口。 当调用其中一种方法时,其行为是委托给服务提供者实例上的相应方法。 每个方法委托给提供者实例的详细信息,请参见每个特定方法的文档。服务提供商实例选择如下:
- 如果定义了系统属性
java.rmi.server.RMIClassLoaderSpi
,那么如果其值等于字符串"default"
,则提供者实例将是通过调用getDefaultProviderInstance()
方法返回的值,对于任何其他值,如果使用属性值命名的类可以由系统类加载器加载(参见ClassLoader.getSystemClassLoader()
),该类可分配给RMIClassLoaderSpi
并具有公共无参数构造函数,那么将调用该构造函数来创建提供者实例。 如果属性被定义,但这些条件中的任何其他条件都不为真,那么未指定的Error
将被抛出到尝试使用RMIClassLoader
代码中,表示无法获取提供者实例。 - 如果名为
META-INF/services/java.rmi.server.RMIClassLoaderSpi
的资源对于系统类加载器是可见的,则该资源的内容将被解释为提供者配置文件,并且该文件中指定的第一个类名被用作提供者类名称。 如果具有该名称的类可以由系统类加载器加载,并且该类可以分配给RMIClassLoaderSpi
并具有公共无参构造函数,则将调用该构造函数来创建提供者实例。 如果找到资源,但提供程序不能如所述实例化,那么未指定的Error
将被抛出到尝试使用RMIClassLoader
代码,指示无法获取提供程序实例。 - 否则,提供者实例将是通过调用
getDefaultProviderInstance()
方法返回的值。
- 从以下版本开始:
- 1.1
- 另请参见:
-
RMIClassLoaderSpi
-
-
-
方法摘要
所有方法 静态方法 具体的方法 弃用的方法 Modifier and Type 方法 描述 static String
getClassAnnotation(Class<?> cl)
返回在编组给定类的对象时,RMI将用于注释类描述符的注释字符串(表示类定义的位置)。static ClassLoader
getClassLoader(String codebase)
返回从给定的代码库URL路径加载类的类加载器。static RMIClassLoaderSpi
getDefaultProviderInstance()
返回服务提供商接口RMIClassLoaderSpi
的默认提供程序的规范实例。static Object
getSecurityContext(ClassLoader loader)
已过时。没有替换。 从Java 2平台v1.2开始,RMI不再使用此方法来获取类加载器的安全上下文。static Class<?>
loadClass(String name)
已过时。替换为loadClass(String,String)
方法static Class<?>
loadClass(String codebase, String name)
从代码库URL路径加载一个类。static Class<?>
loadClass(String codebase, String name, ClassLoader defaultLoader)
从代码库URL路径加载类,可选地使用提供的加载程序。static Class<?>
loadClass(URL codebase, String name)
从代码库URL加载一个类。static Class<?>
loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader)
加载一个动态代理类(请参阅Proxy
),它从代码库URL路径中实现了一组具有给定名称的接口。
-
-
-
方法详细信息
-
loadClass
@Deprecated public static Class<?> loadClass(String name) throws MalformedURLException, ClassNotFoundException
已过时。 替换为loadClass(String,String)
方法加载指定的name
。该方法委托给
loadClass(String,String)
,作为第二个参数传递null
,第二个参数为name
。- 参数
-
name
- 要加载的类的名称 - 结果
-
表示加载类的
Class
对象 - 异常
-
MalformedURLException
- 如果用于加载类的提供者特定URL无效 -
ClassNotFoundException
- 如果在代码库位置找不到类的定义 - 另请参见:
-
loadClass(String,String)
-
loadClass
public static Class<?> loadClass(URL codebase, String name) throws MalformedURLException, ClassNotFoundException
从代码库URL加载一个类。 如果codebase
是null
,那么这个方法将与loadClass(String,String)
的null
codebase
和给定的类名相同。该方法委托给提供者实例的
RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
方法,传递给定URL(或null
如果codebase
为空)时调用URL.toString()
的结果)作为第二个参数,name
作为第二个参数,而null
作为第三个参数。- 参数
-
codebase
- 加载类的URL,或null
-
name
- 要加载的类的名称 - 结果
-
表示加载类的
Class
对象 - 异常
-
MalformedURLException
- 如果codebase
为null
并且用于加载类的提供程序特定URL无效 -
ClassNotFoundException
- 如果在指定的URL处找不到类的定义
-
loadClass
public static Class<?> loadClass(String codebase, String name) throws MalformedURLException, ClassNotFoundException
从代码库URL路径加载一个类。此方法委托给提供者实例的
RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
方法,将codebase
作为第一个参数,name
作为第二个参数,以null
作为第三个参数。- 参数
-
codebase
- 加载类的URL列表(由空格分隔),或null
-
name
- 要加载的类的名称 - 结果
-
表示加载类的
Class
对象 - 异常
-
MalformedURLException
- 如果codebase
非null
并且包含无效的URL,或者如果codebase
是null
并且用于加载类的提供程序特定的URL无效 -
ClassNotFoundException
- 如果在指定位置找不到类的定义 - 从以下版本开始:
- 1.2
-
loadClass
public static Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException
从代码库URL路径加载类,可选地使用提供的加载程序。 当调用者想要向提供者实现提供一个要考虑的附加上下文类加载器时,应该使用此方法,例如堆栈上的调用者的加载程序。 通常,在尝试从代码库URL路径解析类之前,提供者实现将尝试使用给定的defaultLoader
(如果指定)来解析命名类。此方法委托给
RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
提供程序实例的方法,传递codebase
作为第一个参数,name
作为第二个参数,和defaultLoader
作为第三个参数。- 参数
-
codebase
- 加载类的URL列表(由空格分隔),或null
-
name
- 要加载的类的名称 -
defaultLoader
- 要使用的附加上下文类加载器,或null
- 结果
-
表示加载类的
Class
对象 - 异常
-
MalformedURLException
- 如果codebase
不是null
并且包含无效的URL,或者如果codebase
是null
并且用于加载类的提供商特定的URL无效 -
ClassNotFoundException
- 如果在指定位置找不到类的定义 - 从以下版本开始:
- 1.4
-
loadProxyClass
public static Class<?> loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws ClassNotFoundException, MalformedURLException
加载动态代理类(请参阅Proxy
),该代码类从代码库URL路径中实现了一组具有给定名称的接口。接口将被解析为类似于使用给定的
codebase
通过loadClass(String,String)
方法加载的类。此方法委托给提供者实例的
RMIClassLoaderSpi.loadProxyClass(String,String[],ClassLoader)
方法,作为第二个参数传递codebase
作为第二个参数,interfaces
作为第二个参数,defaultLoader
作为第三个参数。- 参数
-
codebase
- 加载类的URL列表(空格分隔),或null
-
interfaces
- 代理类实现的接口的名称 -
defaultLoader
- 要使用的附加上下文类加载器,或null
- 结果
- 一个实现命名接口的动态代理类
- 异常
-
MalformedURLException
- 如果codebase
不是null
并且包含无效的URL,或者如果codebase
是null
并且用于加载类的提供者特定URL无效 -
ClassNotFoundException
- 如果在指定位置找不到某个命名接口的定义,或者如果动态代理类的创建失败(例如,如果Proxy.getProxyClass(ClassLoader,Class[])
将为给定接口列表抛出一个IllegalArgumentException
) - 从以下版本开始:
- 1.4
-
getClassLoader
public static ClassLoader getClassLoader(String codebase) throws MalformedURLException, SecurityException
返回从给定的代码库URL路径加载类的类加载器。返回的类加载器是
loadClass(String,String)
方法用于为相同的codebase
参数加载类的类加载器。该方法委托给提供者实例的
RMIClassLoaderSpi.getClassLoader(String)
方法,传递codebase
作为参数。如果有一个安全管理员,它的
checkPermission
方法将被调用一个RuntimePermission("getClassLoader")
权限; 这可能会导致一个SecurityException
。 该方法的提供者实现还可以执行进一步的安全检查,以验证呼叫上下文是否具有连接到代码库URL路径中的所有URL的权限。- 参数
-
codebase
- 返回的类加载器从其加载类的URL(空格分隔)列表,或null
- 结果
- 一个类加载器,它从给定的代码库URL路径加载类
- 异常
-
MalformedURLException
- 如果codebase
不是null
并且包含无效的URL,或者如果codebase
是null
并且用于标识类加载器的提供者特定URL无效 -
SecurityException
- 如果有安全管理器,并且其checkPermission
方法的调用失败,或者主叫方没有权限连接到代码库URL路径中的所有URL - 从以下版本开始:
- 1.3
-
getClassAnnotation
public static String getClassAnnotation(Class<?> cl)
返回在编组给定类的对象时,RMI将用于注释类描述符的注释字符串(表示类定义的位置)。该方法委托给提供者实例的
RMIClassLoaderSpi.getClassAnnotation(Class)
方法,作为参数传递cl
。- 参数
-
cl
- 获取注释的类 - 结果
-
一个字符串,用于在给定的类进行编组时用于注释,或者是
null
- 异常
-
NullPointerException
- 如果cl
是null
- 从以下版本开始:
- 1.2
-
getDefaultProviderInstance
public static RMIClassLoaderSpi getDefaultProviderInstance()
返回服务提供商接口RMIClassLoaderSpi
的默认提供程序的规范实例。 如果系统属性java.rmi.server.RMIClassLoaderSpi
没有定义,那么RMIClassLoader
静态方法-
loadClass(URL,String)
-
loadClass(String,String)
-
loadClass(String,String,ClassLoader)
-
loadProxyClass(String,String[],ClassLoader)
-
getClassLoader(String)
-
getClassAnnotation(Class)
如果有安全管理员,其
checkPermission
方法将被调用RuntimePermission("setFactory")
权限; 这可能会导致一个SecurityException
。默认服务提供商实例实现
RMIClassLoaderSpi
如下:The
getClassAnnotation
method returns aString
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 bynull
), then the value of thejava.rmi.server.codebase
property (or possibly an earlier cached value) is returned, ornull
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 thegetURLs
methods of the loader. If theURLClassLoader
was created by this provider to service an invocation of itsloadClass
orloadProxyClass
methods, then no permissions are required to get the associated codebase string. If it is an arbitrary otherURLClassLoader
instance, then if there is a security manager, itscheckPermission
method will be invoked once for each URL returned by thegetURLs
method, with the permission returned by invokingopenConnection().getPermission()
on each URL; if any of those invocations throws aSecurityException
or anIOException
, then the value of thejava.rmi.server.codebase
property (or possibly an earlier cached value) is returned, ornull
is returned if that property is not set.Finally, if the class loader is not an instance of
URLClassLoader
, then the value of thejava.rmi.server.codebase
property (or possibly an earlier cached value) is returned, ornull
is returned if that property is not set.
For the implementations of the methods described below, which all take a
String
parameter namedcodebase
that is a space-separated list of URLs, each invocation has an associated codebase loader that is identified using thecodebase
argument in conjunction with the current thread's context class loader (seeThread.getContextClassLoader()
). When there is a security manager, this provider maintains an internal table of class loader instances (which are at least instances ofURLClassLoader
) keyed by the pair of their parent class loader and their codebase URL path (an ordered list of URLs). If thecodebase
argument isnull
, the codebase URL path is the value of the system propertyjava.rmi.server.codebase
or possibly an earlier cached value. For a given codebase URL path passed as thecodebase
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, aSecurityException
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 specifiedname
using thedefaultLoader
, such as by evaluatingClass.forName(name, false, defaultLoader)
If the class is successfully loaded from thedefaultLoader
, that class is returned. If an exception other thanClassNotFoundException
is thrown, that exception is thrown to the caller.Next, the
loadClass
method attempts to load the class with the specifiedname
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 (usingProxy.getProxyClass
) for the resolved interfaces defined in the codebase loader; if that attempt throws anIllegalArgumentException
, it then attempts to obtain a dynamic proxy class for the resolved interfaces defined in thedefaultLoader
. If both attempts throwIllegalArgumentException
, then this method throws aClassNotFoundException
. 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 anIllegalArgumentException
, then this method throws aClassNotFoundException
. - 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.- 结果
- 默认服务提供商的规范实例
- 异常
-
SecurityException
- 如果有安全管理器,并且其checkPermission
方法的调用失败 - 从以下版本开始:
- 1.4
-
-
getSecurityContext
@Deprecated public static Object getSecurityContext(ClassLoader loader)
已过时。 没有替换。 从Java 2平台v1.2开始,RMI不再使用此方法来获取类加载器的安全上下文。返回给定类加载器的安全上下文。- 参数
-
loader
- 从中获取安全上下文的类加载器 - 结果
- 安全上下文
- 另请参见:
-
SecurityManager.getSecurityContext()
-
-