java.lang.Object java.rmi.server.RMIClassLoader
public class RMIClassLoader
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
且具有一个公共无参数的构造方法,则调用构造方法来创建提供者实例。如果定义了属性,但这些条件的所有其他项都不为 true,则向尝试使用 RMIClassLoader
的代码抛出一个不确定的 Error
,以指示获取提供者实例失败。 META-INF/services/java.rmi.server.RMIClassLoaderSpi
的资源对于系统类加载器来说是可见的,则将该资源的内容解释为提供者配置文件,并将在该文件中指定的第一个类名称用作提供者类名称。如果可以通过系统类加载器加载具有该名称的类,并且该类可分配给 RMIClassLoaderSpi
且有一个公共无参数的构造方法,则调用该构造方法以创建提供者实例。如果找到了资源,但无法按描述的方式实例化提供者,则向尝试使用 RMIClassLoader
的代码抛出一个不确定的 Error
,以指示未成功获得提供者实例。 getDefaultProviderInstance()
方法返回的值。
RMIClassLoaderSpi
方法摘要 | |
---|---|
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) 从基本代码 URL 路径加载一个实现一组具有给定名称的接口的动态代理类(请参阅 Proxy )。 |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
方法详细信息 |
---|
@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)
public static Class<?> loadClass(URL codebase, String name) throws MalformedURLException, ClassNotFoundException
codebase
为
null
,则此方法将与具有
null
、
codebase
和给定类名的
loadClass(String,String)
行为相同。
此方法委托给提供者实例的 RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
方法,将在给定 URL 上调用 URL.toString()
的结果(或者如果 codebase
为 null,则为 null
)作为第一个参数、name
为第二个参数和 null
为第三个参数进行传递。
codebase
- 要从其加载类的 URL,或
null
name
- 要加载的类的名称
Class
对象
MalformedURLException
- 如果
codebase
为
null
且用于加载类的特定于提供者的 URL 无效
ClassNotFoundException
- 如果在指定 URL 无法找到该类的定义
public static Class<?> loadClass(String codebase, String name) throws MalformedURLException, ClassNotFoundException
此方法委托给提供者实例的 RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
方法,将 codebase
作为第一个参数、name
为第二个参数和 null
为第三个参数进行传递。
codebase
- 要从其加载类的 URL 的列表(由空格分隔),或者为
null
name
- 要加载的类的名称
Class
对象
MalformedURLException
- 如果
codebase
为非
null
且包含一个无效 URL,或者如果
codebase
为
null
且用于加载类的特定于提供者的 URL 无效。
ClassNotFoundException
- 如果在指定位置无法找到该类的定义
public static Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException
defaultLoader
(如果指定)解析指定的类,然后才试图从代码基 URL 路径解析该类。
此方法委托给提供者实例的 RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
方法,将 codebase
作为第一个参数、name
为第二个参数和 defaultLoader
为第三个参数进行传递。
codebase
- 要从其加载类的 URL 的列表(由空格分隔),或者为
null
name
- 要加载的类的名称
defaultLoader
- 要使用的其他上下文类加载器,或
null
Class
对象
MalformedURLException
- 如果
codebase
为非
null
且包含一个无效 URL,或者如果
codebase
为
null
且用于加载类的特定于提供者的 URL 无效。
ClassNotFoundException
- 如果在指定位置无法找到该类的定义
public static Class<?> loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws ClassNotFoundException, MalformedURLException
Proxy
)。
将解析的接口类似于通过使用给定 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
)
public static ClassLoader getClassLoader(String codebase) throws MalformedURLException, SecurityException
返回的类加载器是 loadClass(String,String)
方法将用来加载相同 codebase
参数的类的类加载器。
此方法委托给提供者实例的 RMIClassLoaderSpi.getClassLoader(String)
方法,将 codebase
作为第一个参数进行传递。
如果存在安全管理器,则使用 RuntimePermission("getClassLoader")
权限调用其 checkPermission
方法;这会导致 SecurityException
。此方法的提供者实现还可以执行进一步的安全检查,以验证调用上下文是否具有连接到代码基 URL 路径中的所有 URL 的权限。
codebase
- 返回的类加载器将从其加载类的 URL 列表(由空格分隔),或
null
MalformedURLException
- 如果
codebase
为非
null
且包含一个无效 URL,或者如果
codebase
为
null
且用于标识类加载器的特定于提供方的 URL 无效
SecurityException
- 如果存在安全管理器且其
checkPermission
方法的调用失败,或者如果调用方没有连接到代码基 URL 路径中所有 URL 的权限
public static String getClassAnnotation(Class<?> cl)
此方法委托给提供者实例的 RMIClassLoaderSpi.getClassAnnotation(Class)
方法,将 cl
作为第一个参数进行传递。
cl
- 要获得其注释的类
null
NullPointerException
- 如果
cl
为
null
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)
如果存在安全管理器,则使用 RuntimePermission("setFactory")
权限调用其 checkPermission
方法;这会导致 SecurityException
。
默认服务提供者实例按以下方式实现 RMIClassLoaderSpi
:
getClassAnnotation
方法返回一个表示基本代码 URL 路径的String
,远程方应使用该路径下载指定类的定义。返回的字符串的格式是一个由空格分隔的 URL 路径。 返回的基本代码字符串取决于指定类的定义类加载器:
- 如果类加载器是系统类加载器(请参阅
ClassLoader.getSystemClassLoader()
)、系统类加载器的父级(如,用于安装扩展的加载器) 或引导类加载器(可以用null
表示),则返回java.rmi.server.codebase
属性的值(或可能是一个原先的缓存值);如果未设置该属性,则返回null
。- 否则,如果类加载器是
URLClassLoader
的实例,则返回的字符串是一个 URL 的外部形式的由空格分隔的列表,该 URL 通过调用加载器getURLs
方法返回。如果URLClassLoader
由此提供者创建,用于调用其loadClass
或loadProxyClass
方法,则不需要任何权限即可获取关联的基本代码字符串。如果它是其他任意一个URLClassLoader
实例,则如果存在安全管理器,则对于getURLs
方法返回的每个 URL 都要调用一次其checkPermission
方法(所用的权限为对每个 URL 调用openConnection().getPermission()
返回的权限);如果这些调用的任何一个抛出SecurityException
或IOException
,则返回java.rmi.server.codebase
属性的值(或可能是原先的缓存值);如果未设置该属性,则返回null
。- 最后,如果类加载器不是
URLClassLoader
的实例,则返回java.rmi.server.codebase
属性的值(或可能是原先的缓存值);如果未设置该属性,则返回null
。对于下面描述的方法的实现,这些实现都采用作为由空格分隔的 URL 列表的名为
codebase
的String
参数,每个调用都有一个关联的基本代码加载器,它通过将codebase
与当前线程的上下文类加载器一起使用进行标识(请参阅Thread.getContextClassLoader()
)。存在安全管理器时,此提供者将维护类加载器实例(至少是URLClassLoader
的实例)的内部表,这些内部表通过其父类加载器及其基本代码 URL 路径(排序的 URL 列表)键入。如果codebase
为null
,则基本代码 URL 路径是系统属性java.rmi.server.codebase
的值,或可能是原先的缓存值。对于给定的基本代码 URL 路径(该路径作为codebase
参数传递到下面给定上下文中的方法之一的调用),基本代码加载器位于具有指定基本代码 URL 路径的表中且当前线程的上下文类加载器是其父级的加载器。如果不存在这样的加载器,则创建一个这样的加载器并将其添加到表中。该表不维护对其包含的加载器的强引用,以便于允许它们及其定义类在不可另外到达时被垃圾回收。为了防止不受信任的任意代码被隐式加载到不带安全管理器的虚拟机中,如果未设置安全管理器,则基本代码加载器就是当前线程的上下文类加载器(提供的基本代码 URL 路径被忽略,所以禁止了远程类加载)。
getClassLoader
方法返回指定基本代码 URL 路径的基本代码加载器。如果存在安全管理器,则如果该调用上下文没有连接到基本代码 URL 路径上的所有 URL 的权限,则抛出SecurityException
。
loadClass
方法尝试按以下方式加载具有指定名称的类:如果defaultLoader
为非null
,则它首先尝试使用defaultLoader
加载具有指定name
的类,比如通过评估Class.forName(name, false, defaultLoader)如果从defaultLoader
成功加载了类,则返回该类。如果抛出ClassNotFoundException
之外的异常,则该异常被抛给调用方。其次,
loadClass
方法尝试使用指定基本代码 URL 路径的基本代码加载器加载具有指定name
的类。如果存在安全管理器,则该调用上下文必须具有连接到基本代码 URL 上的所有 URL 的权限;否则,将使用当前线程的上下文类加载器,而不是基本代码加载器。
loadProxyClass
方法尝试按以下方式返回具有指定接口的动态代理类:如果
defaultLoader
参数为非null
且可以通过该加载器解析所有指定接口,则,
- 如果所有解析的接口都为
public
,则它首先尝试获得在基本代码加载器中定义的解析接口的动态代理类(使用Proxy.getProxyClass
);如果该尝试抛出一个IllegalArgumentException
,则它尝试获得在defaultLoader
中定义的解析接口的动态代理类。如果两个尝试都抛出IllegalArgumentException
,则此方法将抛出ClassNotFoundException
。如果抛出任何其他异常,则该异常将被抛给调用方。- 如果在同一类加载器中定义所有非
public
解析接口,则其尝试获得在该加载器中定义的解析接口的动态代理类。- 否则,抛出
LinkageError
(因为实现所有指定接口的类无法在任何加载器中定义)。否则,如果所有指定的接口可通过基本代码加载器解析,则,
- 如果所有解析接口都为
public
,则它尝试获得基本代码中解析接口的动态代理类。如果该尝试抛出IllegalArgumentException
,则此方法抛出一个ClassNotFoundException
。- 如果在同一类加载器中定义所有非
public
解析接口,则它尝试获得在该加载器中定义的解析接口的动态代理类。- 否则,抛出
LinkageError
(因为实现所有指定接口的类无法在任何加载器中定义)。否则,将为每个无法解析的指定接口抛出
ClassNotFoundException
。
SecurityException
- 如果存在安全管理器,且其
checkPermission
方法的调用将失败
@Deprecated public static Object getSecurityContext(ClassLoader loader)
loader
- 从其获取安全上下文的类加载器
SecurityManager.getSecurityContext()