模块  java.rmi
软件包  java.rmi.server

Class RMIClassLoader


  • public class RMIClassLoaderextends Object
    RMIClassLoader包含静态方法以支持使用RMI进行动态类加载。 包括从网络位置(一个或多个URL)加载类并获取远程方应从其加载现有类的位置的方法。 当参数中包含的编组和解组类以及远程方法调用的返回值时,RMI运行时使用这些方法,并且它们也可以由应用程序直接调用,以模仿RMI的动态类加载行为。

    执行以下静态方法

    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
    • 方法详细信息

      • loadClass

        public static <?> 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
        结果
        表示已加载类的 对象
        异常
        MalformedURLException - 如果 codebase不是 null且包含无效的URL,或者 codebasenull且用于加载类的提供程序特定的URL无效
        ClassNotFoundException - 如果在指定位置找不到类的定义
        从以下版本开始:
        1.4
      • loadProxyClass

        public static <?> 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,或者 codebasenull且用于加载类的提供程序特定的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作为参数传递。

        如果有安全经理,将以RuntimePermission("getClassLoader")权限调用其checkPermission方法; 这可能导致SecurityException 此方法的提供程序实现还可以执行进一步的安全检查,以验证调用上下文是否具有连接到代码库URL路径中的所有URL的权限。

        参数
        codebase - 返回的类加载器将从中加载类的URL列表(以空格分隔),或 null
        结果
        一个类加载器,它从给定的代码库URL路径加载类
        异常
        MalformedURLException - 如果 codebase不是 null且包含无效的URL,或者 codebasenull且用于标识类加载器的提供程序特定的URL无效
        SecurityException - 如果存在安全管理器并且其 checkPermission方法的调用失败,或者调用者没有权限连接到代码库URL路径中的所有URL
        从以下版本开始:
        1.3
      • getClassAnnotation

        public static String getClassAnnotation​(<?> cl)
        返回注释字符串(表示类定义的位置),RMI将在编组给定类的对象时用于注释类描述符。

        此方法委托提供程序实例的RMIClassLoaderSpi.getClassAnnotation(Class)方法,传递cl作为参数。

        参数
        cl - 获取注释的类
        结果
        在被编组时用于注释给定类的字符串,或 null
        异常
        NullPointerException - 如果 clnull
        从以下版本开始:
        1.2
      • getDefaultProviderInstance

        public static RMIClassLoaderSpi getDefaultProviderInstance()
        返回服务提供者接口RMIClassLoaderSpi的默认提供者的规范实例。 如果未定义系统属性java.rmi.server.RMIClassLoaderSpiRMIClassLoader静态方法 将使用默认提供程序的规范实例作为服务提供程序实例。

        如果有安全管理器,将使用RuntimePermission("setFactory")权限调用其checkPermission方法; 这可能导致SecurityException

        默认服务提供程序实例实现RMIClassLoaderSpi ,如下所示:

        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.

        结果
        默认服务提供者的规范实例
        异常
        SecurityException - 如果有安全管理器并且其 checkPermission方法的调用失败
        从以下版本开始:
        1.4
      • getSecurityContext

        @Deprecatedpublic static Object getSecurityContext​(ClassLoader loader)
        Deprecated.
        no replacement. As of the Java 2 platform v1.2, RMI no longer uses this method to obtain a class loader's security context.
        返回给定类加载器的安全上下文。
        参数
        loader - 从中获取安全上下文的类加载器
        结果
        安全上下文
        另请参见:
        SecurityManager.getSecurityContext()