模块 java.base
 java.lang

类 ClassLoader

java.lang.Object
java.lang.ClassLoader
已知子类:
SecureClassLoader

public abstract class ClassLoader extends Object
类加载器是负责加载类的对象。类 ClassLoader 是一个抽象类。给定类的二进制名称,类加载器应该尝试定位或生成构成类定义的数据。典型的策略是将名称转换为文件名,然后从文件系统中读取该名称的“类文件”。

每个 Class 对象都包含一个 reference 到定义它的 ClassLoader

Class 数组类的对象不是由类加载器创建的,而是根据 Java 运行时的要求自动创建的。 Class.getClassLoader() 返回的数组类的类加载器与其元素类型的类加载器相同;如果元素类型是原始类型,则数组类没有类加载器。

应用程序实现 ClassLoader 的子类,以扩展 Java 虚拟机动态加载类的方式。

安全管理器通常可以使用类加载器来指示安全域。

除了加载类之外,类加载器还负责定位资源。资源是一些数据(例如“.class”文件、配置数据或图像),用抽象的“/”分隔路径名标识。资源通常与应用程序或库打包在一起,以便可以通过应用程序或库中的代码定位它们。在某些情况下,资源被包括在内,以便其他图书馆可以找到它们。

ClassLoader 类使用委托模型来搜索类和资源。 ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例通常会在尝试查找类或资源本身之前将类或资源的搜索委托给其父类加载器。

支持并发加载类的类加载器称为 parallel capable 类加载器,需要在类初始化时调用 ClassLoader.registerAsParallelCapable 方法来注册自己。请注意,ClassLoader 类默认注册为具有并行能力。但是,如果它们的子类具有并行能力,它们仍然需要自行注册。在委托模型不是严格分层的环境中,类加载器需要具有并行能力,否则类加载会导致死锁,因为加载器锁在类加载过程中一直保持(参见loadClass 方法)。

运行时内置类加载器

Java 运行时具有以下内置类加载器:
  • 引导类加载器。它是虚拟机的内置类加载器,通常表示为 null ,并且没有父类。

  • 平台类加载器。平台类加载器负责加载 platform classes 。平台类包括 Java SE 平台 API、它们的实现类和由平台类加载器或其祖先定义的特定于 JDK 的运行时类。平台类加载器可以用作 ClassLoader 实例的父级。

    为了允许升级/重写定义到平台类加载器的模块,并且升级模块读取定义到类加载器而不是平台类加载器及其祖先的模块,那么平台类加载器可能必须委托给其他类加载器,例如应用程序类加载器。换句话说,定义给类加载器而不是平台类加载器及其祖先的命名模块中的类可能对平台类加载器可见。

  • 系统类加载器。它也称为 application class loader,与平台类加载器不同。系统类加载器通常用于在应用程序类路径、模块路径和 JDK 特定工具上定义类。平台类加载器是系统类加载器的父级或祖先,因此系统类加载器可以通过委托给其父级来加载平台类。

通常,Java 虚拟机以平台相关的方式从本地文件系统加载类。但是,某些类可能不是来自文件;它们可能来自其他来源,例如网络,或者它们可以由应用程序构建。 defineClass 方法将字节数组转换为类 Class 的实例。可以使用 Class.newInstance 创建这个新定义类的实例。

类加载器创建的对象的方法和构造函数可以引用其他类。为了确定引用的类,Java 虚拟机调用最初创建该类的类加载器的loadClass 方法。

例如,应用程序可以创建网络类加载器以从服务下载类文件。示例代码可能如下所示:

  ClassLoader loader = new NetworkClassLoader(host, port);
  Object main = loader.loadClass("Main", true).newInstance();
     . . .
 

网络类加载器子类必须定义方法 findClass loadClassData 以从网络加载类。一旦它下载了构成类的字节,它应该使用方法defineClass 来创建一个类实例。一个示例实现是:

   class NetworkClassLoader extends ClassLoader {
     String host;
     int port;

     public Class findClass(String name) {
       byte[] b = loadClassData(name);
       return defineClass(name, b, 0, b.length);
     }

     private byte[] loadClassData(String name) {
       // load the class data from the connection
        . . .
     }
   }
 

二进制名称

作为 String 参数提供给 ClassLoader 中的方法的任何类名必须是二进制名称,由Java 语言规范.

有效类名的示例包括:

  "java.lang.String"
  "javax.swing.JSpinner$DefaultEditor"
  "java.security.KeyStore$Builder$FileBuilder$1"
  "java.net.URLClassLoader$3$1"
 

作为 String 参数提供给 ClassLoader 中的方法的任何包名称必须是空字符串(表示未命名的包)或由定义的完全限定名称Java 语言规范.

Java 语言规范:
6.7 完全限定名称
13.1 二进制形式
自从:
1.0
参见:
  • 构造方法详细信息

    • ClassLoader

      protected ClassLoader(String  name, ClassLoader  parent)
      创建指定名称的新类加载器并使用指定的父类加载器进行委托。
      API 注意:
      如果父级指定为 null(用于引导类加载器),则无法保证所有平台类都可见。
      参数:
      name - 类加载器名称;或者 null 如果没有命名
      parent - 父类加载器
      抛出:
      IllegalArgumentException - 如果给定名称为空。
      SecurityException - 如果安全管理器存在且其 SecurityManager.checkCreateClassLoader() 方法不允许创建新的类加载器。
      自从:
      9
    • ClassLoader

      protected ClassLoader(ClassLoader  parent)
      使用指定的父类加载器创建一个新的类加载器进行委托。

      如果有安全管理器,则调用其 checkCreateClassLoader 方法。这可能会导致安全异常。

      API 注意:
      如果父级指定为 null(用于引导类加载器),则无法保证所有平台类都可见。
      参数:
      parent - 父类加载器
      抛出:
      SecurityException - 如果安全管理器存在且其 checkCreateClassLoader 方法不允许创建新的类加载器。
      自从:
      1.2
    • ClassLoader

      protected ClassLoader()
      使用方法 getSystemClassLoader() 返回的 ClassLoader 创建一个新的类加载器作为父类加载器。

      如果有安全管理器,则调用其 checkCreateClassLoader 方法。这可能会导致安全异常。

      抛出:
      SecurityException - 如果安全管理器存在且其 checkCreateClassLoader 方法不允许创建新的类加载器。
  • 方法详情

    • getName

      public String  getName()
      返回此类加载器的名称,如果未命名此类加载器,则返回 null
      API 注意:
      此方法不是最终的兼容性。如果重写此方法,则此方法必须返回与实例化此类加载器时指定的名称相同的名称。
      返回:
      此类加载器的名称;或者 null 如果这个类加载器没有命名。
      自从:
      9
    • loadClass

      public Class <?> loadClass(String  name) throws ClassNotFoundException
      使用指定的 二进制名称 加载类。此方法以与 loadClass(String, boolean) 方法相同的方式搜索类。 Java 虚拟机调用它来解析类引用。调用此方法等同于调用 loadClass(name, false)
      参数:
      name - 类的 二进制名称
      返回:
      生成的 Class 对象
      抛出:
      ClassNotFoundException - 如果找不到该类
    • loadClass

      protected Class <?> loadClass(String  name, boolean resolve) throws ClassNotFoundException
      使用指定的 二进制名称 加载类。此方法的默认实现按以下顺序搜索类:
      1. 调用 findLoadedClass(String) 检查类是否已经加载。

      2. 在父类加载器上调用 loadClass 方法。如果父级是null,则使用虚拟机内置的类加载器。

      3. 调用 findClass(String) 方法来查找类。

      如果使用上述步骤找到该类,并且 resolve 标志为真,则此方法将在生成的 Class 对象上调用 resolveClass(Class) 方法。

      鼓励 ClassLoader 的子类覆盖 findClass(String) ,而不是这个方法。

      除非被重写,否则此方法会在整个类加载过程中同步 getClassLoadingLock 方法的结果。

      参数:
      name - 类的 二进制名称
      resolve - 如果 true 然后解析类
      返回:
      生成的 Class 对象
      抛出:
      ClassNotFoundException - 如果找不到该类
    • getClassLoadingLock

      protected Object  getClassLoadingLock(String  className)
      返回类加载操作的锁对象。为了向后兼容,此方法的默认实现行为如下。如果此 ClassLoader 对象注册为具有并行能力,则该方法返回与指定类名关联的专用对象。否则,该方法返回此 ClassLoader 对象。
      参数:
      className - 待加载类的名称
      返回:
      类加载操作的锁
      抛出:
      NullPointerException - 如果注册为支持并行且 className 为空
      自从:
      1.7
      参见:
    • findClass

      protected Class <?> findClass(String  name) throws ClassNotFoundException
      查找具有指定 二进制名称 的类。此方法应由遵循加载类委托模型的类加载器实现覆盖,并将在检查所请求类的父类加载器后由 loadClass 方法调用。
      实现要求:
      默认实现抛出 ClassNotFoundException
      参数:
      name - 类的 二进制名称
      返回:
      生成的 Class 对象
      抛出:
      ClassNotFoundException - 如果找不到该类
      自从:
      1.2
    • findClass

      protected Class <?> findClass(String  moduleName, String  name)
      在为此类加载器定义的模块中查找具有给定 二进制名称 的类。支持从模块加载的类加载器实现应该覆盖此方法。
      API 注意:
      如果找不到该类,此方法将返回 null 而不是抛出 ClassNotFoundException
      实现要求:
      moduleNamenull 时,默认实现尝试通过调用 findClass(String) 来查找类。否则返回 null
      参数:
      moduleName - 模块名称;或 null未命名模块 中为此类加载器查找类
      name - 类的 二进制名称
      返回:
      生成的 Class 对象,或 null(如果找不到该类)。
      自从:
      9
    • defineClass

      @Deprecated (since ="1.1") protected final Class <?> defineClass(byte[] b, int off, int len) throws ClassFormatError
      将字节数组转换为类 Class 的实例。在使用 Class 之前,必须解决它。此方法已弃用,取而代之的是将 二进制名称 作为其第一个参数的版本,并且更安全。
      参数:
      b - 构成类数据的字节。位置 offoff+len-1 中的字节应具有由定义的有效类文件的格式Java 虚拟机规范.
      off - 类数据的 b 中的起始偏移量
      len - 类数据的长度
      返回:
      从指定类数据创建的 Class 对象
      抛出:
      ClassFormatError - 如果数据不包含有效类
      IndexOutOfBoundsException - 如果 offlen 为负,或者如果 off+len 大于 b.length
      SecurityException - 如果尝试将此类添加到包含由与此类不同的一组证书签名的类的包中,或者如果尝试在包中定义具有完全限定名称的类以“java.”开头。
      参见:
    • defineClass

      protected final Class <?> defineClass(String  name, byte[] b, int off, int len) throws ClassFormatError
      将字节数组转换为类 Class 的实例。在使用 Class 之前,必须解决它。

      此方法将默认值 ProtectionDomain 分配给新定义的类。 ProtectionDomain 被有效授予调用 Policy.getPolicy().getPermissions(new CodeSource(null, null)) 时返回的同一组权限。默认保护域在第一次调用 defineClass 时创建,并在后续调用中重新使用。

      要将特定的 ProtectionDomain 分配给类,请使用将 ProtectionDomain 作为其参数之一的 defineClass 方法。

      这个方法在这个类加载器中定义了一个对应于Class包的包(如果这个类加载器中还没有定义这样的包)。定义包的名称是从字节数组b指定的类的二进制名称派生的。定义包的其他属性由 Package 指定。

      参数:
      name - 类的预期 二进制名称,如果未知则为 null
      b - 构成类数据的字节。位置 offoff+len-1 中的字节应具有由定义的有效类文件的格式Java 虚拟机规范.
      off - 类数据的 b 中的起始偏移量
      len - 类数据的长度
      返回:
      从指定类数据创建的 Class 对象。
      抛出:
      ClassFormatError - 如果数据不包含有效类
      IndexOutOfBoundsException - 如果 offlen 为负,或者如果 off+len 大于 b.length
      SecurityException - 如果尝试将此类添加到包含由与此类(未签名)不同的一组证书签名的类的包,或者如果 name 以“java.”开头。
      自从:
      1.1
      参见:
    • defineClass

      protected final Class <?> defineClass(String  name, byte[] b, int off, int len, ProtectionDomain  protectionDomain) throws ClassFormatError
      使用给定的 ProtectionDomain 将字节数组转换为类 Class 的实例。

      如果给定的 ProtectionDomainnull,则默认保护域将分配给 defineClass(String, byte[], int, int) 文档中指定的类。在可以使用该类之前,必须对其进行解析。

      包中定义的第一个类确定了该包中定义的所有后续类必须包含的确切证书集。类的证书集是从类的 ProtectionDomain 中的 CodeSource 获得的。添加到该包的任何类都必须包含相同的证书集,否则将抛出 SecurityException。请注意,如果 namenull,则不会执行此检查。您应该始终传入您正在定义的类的 二进制名称 以及字节。这确保您定义的类确实是您认为的类。

      如果指定的name以“java.”开头,则只能由平台类加载器或其祖先定义;否则将抛出 SecurityException。如果 name 不是 null ,它必须等于字节数组 b 指定的类的 二进制名称,否则将抛出 NoClassDefFoundError

      这个方法在这个类加载器中定义了一个对应于Class包的包(如果这个类加载器中还没有定义这样的包)。定义包的名称是从字节数组b指定的类的二进制名称派生的。定义包的其他属性由 Package 指定。

      参数:
      name - 类的预期 二进制名称,如果未知则为 null
      b - 构成类数据的字节。位置 offoff+len-1 中的字节应具有由定义的有效类文件的格式Java 虚拟机规范.
      off - 类数据的 b 中的起始偏移量
      len - 类数据的长度
      protectionDomain - 类的 ProtectionDomain
      返回:
      从数据创建的 Class 对象,以及 ProtectionDomain
      抛出:
      ClassFormatError - 如果数据不包含有效类
      NoClassDefFoundError - 如果 name 不是 null 且不等于 b 指定的类的 二进制名称
      IndexOutOfBoundsException - 如果 offlen 为负,或者如果 off+len 大于 b.length
      SecurityException - 如果尝试将此类添加到包含由与此类不同的一组证书签名的类的包中,或者如果 name 以“java. ”开头并且此类加载器不是平台类加载器或其祖先。
    • defineClass

      protected final Class <?> defineClass(String  name, ByteBuffer  b, ProtectionDomain  protectionDomain) throws ClassFormatError
      使用给定的 ProtectionDomainByteBuffer 转换为类 Class 的实例。如果给定的 ProtectionDomainnull,则默认保护域将分配给 defineClass(String, byte[], int, int) 文档中指定的类。在可以使用该类之前,必须对其进行解析。

      关于包中定义的第一个类确定包的证书集、类名称的限制以及类的定义包的规则与 defineClass(String, byte[], int, int, ProtectionDomain) 的文档中指定的规则相同。

      调用此表单方法.defineClass( name, b缓冲区, PD) 产生与语句完全相同的结果

      ...
      byte[] temp = new byte[bBuffer.remaining()];
      bBuffer.get(temp);
      return cl.defineClass(name, temp, 0, temp.length, pd);

      参数:
      name - 预期的 二进制名称 。类的,或者 null 如果不知道
      b - 构成类数据的字节。从位置 b.position()b.position() + b.limit() -1 的字节应该具有由定义的有效类文件的格式Java 虚拟机规范.
      protectionDomain - 类的 ProtectionDomainnull
      返回:
      从数据创建的 Class 对象,以及 ProtectionDomain
      抛出:
      ClassFormatError - 如果数据不包含有效类。
      NoClassDefFoundError - 如果 name 不是 null 且不等于 b 指定的类的 二进制名称
      SecurityException - 如果尝试将此类添加到包含由与此类不同的一组证书签名的类的包,或者如果 name 以“java.”开头。
      自从:
      1.5
      参见:
    • resolveClass

      protected final void resolveClass(Class <?> c)
      链接指定的类。这个(误导性命名的)方法可能被类加载器用来链接一个类。如果类 c 已经被链接,那么这个方法简单地返回。否则,该类将按照“执行”一章中的描述进行链接Java 语言规范.
      参数:
      c - 要链接的类
      抛出:
      NullPointerException - 如果 cnull
      参见:
    • findSystemClass

      protected final Class <?> findSystemClass(String  name) throws ClassNotFoundException
      查找具有指定 二进制名称 的类,必要时加载它。

      此方法通过系统类加载器加载类(请参阅 getSystemClassLoader() )。返回的 Class 对象可能关联了多个 ClassLoaderClassLoader 的子类通常不需要调用此方法,因为大多数类加载器只需要覆盖 findClass(String)

      参数:
      name - 类的 二进制名称
      返回:
      指定nameClass对象
      抛出:
      ClassNotFoundException - 如果找不到该类
      参见:
    • findLoadedClass

      protected final Class <?> findLoadedClass(String  name)
      如果此加载器已被 Java 虚拟机记录为具有该 二进制名称 的类的初始加载器,则返回具有给定 二进制名称 的类。否则返回 null
      参数:
      name - 类的 二进制名称
      返回:
      Class 对象,或 null(如果类尚未加载)
      自从:
      1.1
    • setSigners

      protected final void setSigners(Class <?> c, Object [] signers)
      设置类的签名者。这应该在定义一个类之后调用。
      参数:
      c - Class 对象
      signers - 类的签名者
      自从:
      1.1
    • findResource

      protected URL  findResource(String  moduleName, String  name) throws IOException
      返回指向此类加载器定义的模块中资源的 URL。支持从模块加载的类加载器实现应该重写此方法。
      API 注意:
      此方法是 Class.getResource Class.getResourceAsStream Module.getResourceAsStream 方法的基础。它不受 Module.getResourceAsStream 指定的封装规则的约束。
      实现要求:
      moduleNamenull 时,默认实现尝试通过调用 findResource(String) 来查找资源。否则返回 null
      参数:
      moduleName - 模块名称;或 null未命名模块 中为此类加载器查找资源
      name - 资源名称
      返回:
      资源的 URL; null 如果找不到资源,则无法构造 URL 来定位资源,安全管理器拒绝访问资源,或者没有为类加载器定义给定名称的模块。
      抛出:
      IOException - 如果发生 I/O 错误
      自从:
      9
      参见:
    • getResource

      public URL  getResource(String  name)
      查找具有给定名称的资源。资源是一些数据(图像、音频、文本等),可以通过类代码以独立于代码位置的方式访问。

      资源的名称是标识资源的以“/”分隔的路径名。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包为 opened 时无条件地在命名模块的包中查找资源(即使此方法的调用者在同一模块中作为资源)。

      API 注意:
      如果多个模块被定义到同一个类加载器,并且多个模块包含具有给定名称的资源,则搜索模块的顺序未指定并且可能非常不可预测。覆盖此方法时,建议实现确保任何委托与 getResources(String) 方法一致。
      实现要求:
      默认实现会先在父类加载器中搜索资源;如果父级是null,则搜索虚拟机中内置的类加载器的路径。如果未找到,此方法将调用 findResource(String) 来查找资源。
      参数:
      name - 资源名称
      返回:
      URL 用于读取资源的对象; null 如果找不到资源,则无法构造 URL 来定位资源,资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。
      抛出:
      NullPointerException - 如果 namenull
      自从:
      1.1
    • getResources

      public Enumeration <URL > getResources(String  name) throws IOException
      查找具有给定名称的所有资源。资源是一些数据(图像、音频、文本等),可以通过类代码以独立于代码位置的方式访问。

      资源的名称是标识资源的 / 分隔路径名。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包为 opened 时无条件地在命名模块的包中查找资源(即使此方法的调用者在同一模块中作为资源)。

      API 注意:
      如果多个模块被定义到同一个类加载器,并且多个模块包含具有给定名称的资源,则没有指定顺序并且可能非常不可预测。覆盖此方法时,建议实现确保任何委托与 getResource(String) 方法一致。这应确保枚举的 nextElement 方法返回的第一个元素与 getResource(String) 方法将返回的资源相同。
      实现要求:
      默认实现会先在父类加载器中搜索资源;如果父级是null,则搜索虚拟机中内置的类加载器的路径。然后它调用 findResources(String) 以在此类加载器中查找具有该名称的资源。它返回一个枚举,其元素是通过搜索父类加载器找到的 URL,然后是使用 findResources 找到的元素。
      参数:
      name - 资源名称
      返回:
      资源的 URL 对象枚举。如果找不到资源,枚举将为空。无法构造 URL 的资源位于未无条件打开的包中,或者安全管理器拒绝访问资源,不会在枚举中返回。
      抛出:
      IOException - 如果发生 I/O 错误
      NullPointerException - 如果 namenull
      自从:
      1.2
    • resources

      public Stream <URL > resources(String  name)
      返回一个流,其元素是具有给定名称的所有资源的 URL。资源是一些数据(图像、音频、文本等),可以通过类代码以独立于代码位置的方式访问。

      资源的名称是标识资源的 / 分隔路径名。

      评估返回的流时将定位资源。如果计算结果为 IOException,则 I/O 异常被包装在 UncheckedIOException 中,然后被抛出。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包为 opened 时无条件地在命名模块的包中查找资源(即使此方法的调用者在同一模块中作为资源)。

      API 注意:
      覆盖此方法时,建议实现确保任何委托与 getResource(String) 方法一致。这应确保流返回的第一个元素与 getResource(String) 方法将返回的资源相同。
      实现要求:
      默认实现调用 getResources 来查找具有给定名称的所有资源,并返回一个以枚举中的元素作为源的流。
      参数:
      name - 资源名称
      返回:
      资源 URL 对象流。如果找不到资源,则流将为空。无法构造 URL 的资源,位于未无条件打开的包中,或者安全管理器拒绝访问资源,将不会在流中。
      抛出:
      NullPointerException - 如果 namenull
      自从:
      9
    • findResource

      protected URL  findResource(String  name)
      查找具有给定名称的资源。类加载器实现应该重写这个方法。

      对于命名模块中的资源,该方法必须实施 Module getResourceAsStream 方法中指定的封装规则。此外,它不能在命名模块的包中找到非“.class”资源,除非包是无条件的opened

      实现要求:
      默认实现返回 null
      参数:
      name - 资源名称
      返回:
      URL 用于读取资源的对象; null 如果找不到资源,则无法构造 URL 来定位资源,资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。
      自从:
      1.2
    • findResources

      protected Enumeration <URL > findResources(String  name) throws IOException
      返回代表具有给定名称的所有资源的 URL 对象的枚举。类加载器实现应该覆盖这个方法。

      对于命名模块中的资源,该方法必须实施 Module getResourceAsStream 方法中指定的封装规则。此外,它不能在命名模块的包中找到非“.class”资源,除非包是无条件的opened

      实现要求:
      默认实现返回一个不包含任何元素的枚举。
      参数:
      name - 资源名称
      返回:
      资源的 URL 对象枚举。如果找不到资源,枚举将为空。无法构造 URL 的资源位于未无条件打开的包中,或者安全管理器拒绝访问资源,不会在枚举中返回。
      抛出:
      IOException - 如果发生 I/O 错误
      自从:
      1.2
    • registerAsParallelCapable

      protected static boolean registerAsParallelCapable()
      将调用者注册为 并行能力 。注册成功当且仅当满足以下所有条件:
      1. 没有创建调用者的实例
      2. 调用者的所有超类(类 Object 除外)都注册为具有并行能力

      请注意,一旦类加载器注册为具有并行能力,就无法将其更改回来。

      如果此方法是从调用者不是 ClassLoader 的子类或堆栈上没有调用者框架的上下文调用的(例如,当直接从 JNI 附加线程调用时),则抛出 IllegalCallerException

      返回:
      true 如果调用者成功注册为具有并行能力,否则为 false
      抛出:
      IllegalCallerException - 如果调用者不是 ClassLoader 的子类
      自从:
      1.7
      参见:
    • isRegisteredAsParallelCapable

      public final boolean isRegisteredAsParallelCapable()
      如果此类加载器注册为 并行能力,则返回 true,否则返回 false
      返回:
      true 如果此类加载器具有并行能力,否则 false
      自从:
      9
      参见:
    • getSystemResource

      public static URL  getSystemResource(String  name)
      从用于加载类的搜索路径中查找指定名称的资源。该方法通过系统类加载器定位资源(参见 getSystemClassLoader() )。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包无条件为opened 时在命名模块的包中查找资源。

      参数:
      name - 资源名称
      返回:
      URL 到资源; null 如果找不到资源,无法构造 URL 来定位资源,资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。
      自从:
      1.1
    • getSystemResources

      public static Enumeration <URL > getSystemResources(String  name) throws IOException
      从用于加载类的搜索路径中查找指定名称的所有资源。这样找到的资源将作为 Enumeration 个对象中的 URL 个对象返回。

      getSystemResource(String) 的文档中描述了搜索顺序。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包无条件为opened 时在命名模块的包中查找资源。

      参数:
      name - 资源名称
      返回:
      资源的 URL 对象枚举。如果找不到资源,枚举将为空。无法构造 URL 的资源位于未无条件打开的包中,或者安全管理器拒绝访问资源,不会在枚举中返回。
      抛出:
      IOException - 如果发生 I/O 错误
      自从:
      1.2
    • getResourceAsStream

      public InputStream  getResourceAsStream(String  name)
      返回用于读取指定资源的输入流。

      getResource(String) 的文档中描述了搜索顺序。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包无条件为opened 时在命名模块的包中查找资源。

      参数:
      name - 资源名称
      返回:
      用于读取资源的输入流; null 如果找不到资源,则资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。
      抛出:
      NullPointerException - 如果 namenull
      自从:
      1.1
    • getSystemResourceAsStream

      public static InputStream  getSystemResourceAsStream(String  name)
      打开以供阅读,用于加载类的搜索路径中指定名称的资源。该方法通过系统类加载器定位资源(参见 getSystemClassLoader() )。

      命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。此外,除了资源名称以“.class”结尾的特殊情况外,此方法只会在包无条件为opened 时在命名模块的包中查找资源。

      参数:
      name - 资源名称
      返回:
      用于读取资源的输入流; null 如果找不到资源,则资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。
      自从:
      1.1
    • getParent

      public final ClassLoader  getParent()
      返回委托的父类加载器。一些实现可能使用 null 来表示引导类加载器。如果此类加载器的父类是引导类加载器,则此方法将在此类实现中返回 null
      返回:
      父母ClassLoader
      抛出:
      SecurityException - 如果存在安全管理器,并且调用者的类加载器不是 null 并且不是此类加载器的祖先,并且调用者没有 RuntimePermission ("getClassLoader")
      自从:
      1.2
    • getUnnamedModule

      public final Module  getUnnamedModule()
      返回此类加载器的未命名 Module
      返回:
      此类加载器的未命名模块
      自从:
      9
      参见:
    • getPlatformClassLoader

      public static ClassLoader  getPlatformClassLoader()
      返回平台类加载器。所有 平台类 对平台类加载器都是可见的。
      实现注意事项:
      内置平台类加载器的名称是 "platform"
      返回:
      平台ClassLoader
      抛出:
      SecurityException - 如果存在安全管理器,并且调用者的类加载器不是 null ,并且调用者的类加载器与平台类加载器不同或不是平台类加载器的祖先,并且调用者没有 RuntimePermission ("getClassLoader")
      自从:
      9
    • getSystemClassLoader

      public static ClassLoader  getSystemClassLoader()
      返回系统类加载器。这是新 ClassLoader 实例的默认委托父级,通常是用于启动应用程序的类加载器。

      此方法首先在运行时启动序列的早期调用,此时它创建系统类加载器。这个类加载器将是主应用程序线程(例如,调用主类的main方法的线程)的上下文类加载器。

      默认系统类加载器是此类的依赖于实现的实例。

      如果在首次调用此方法时定义了系统属性“java.system.class.loader”,则该属性的值将被视为将作为系统类加载器返回的类的名称。该类是使用默认系统类加载器加载的,并且必须定义一个公共构造函数,该构造函数采用类型为 ClassLoader 的单个参数,用作委托父级。然后使用此构造函数创建一个实例,并将默认系统类加载器作为参数。生成的类加载器被定义为系统类加载器。在构造过程中,类加载器应该非常小心,避免调用 getSystemClassLoader() 。如果检测到系统类加载器的循环初始化,则会抛出 IllegalStateException

      实现注意事项:
      在 VM 几乎完全初始化之前,不会检查重写系统类加载器的系统属性。在启动期间执行此方法的代码应注意在系统完全初始化之前不要缓存返回值。

      内置系统类加载器的名称是 "app" 。在 VM 的早期初始化期间读取系统属性“java.class.path”以确定类路径。根据初始模块(包含主类的模块)是命名还是未命名,“java.class.path”属性的空值被不同地解释:如果命名,内置系统类加载器将没有类路径并将搜索类和使用应用程序模块路径的资源;否则,如果未命名,它将把类路径设置为当前工作目录。

      类路径上的 JAR 文件可能包含一个 Class-Path 清单属性以指定要包含在类路径中的依赖 JAR 文件。 Class-Path 条目必须满足特定的有效性条件(有关详细信息,请参阅 JAR 文件规范)。无效的 Class-Path 条目将被忽略。出于调试目的,如果 jdk.net.URLClassPath.showIgnoredClassPathEntries 系统属性设置为 true,则可以将忽略的条目打印到控制台。

      返回:
      系统ClassLoader
      抛出:
      SecurityException - 如果存在安全管理器,并且调用者的类加载器不是 null 并且与系统类加载器不同或不是系统类加载器的祖先,并且调用者没有 RuntimePermission ("getClassLoader")
      IllegalStateException - 如果在构造由“java.system.class.loader”属性指定的类加载器期间递归调用。
      Error - 如果定义了系统属性“java.system.class.loader”但命名的类无法加载,则提供程序类未定义所需的构造函数,或者该构造函数在调用时抛出异常。可以通过 Throwable.getCause() 方法检索错误的根本原因。
    • definePackage

      protected   definePackage(String  name, String  specTitle, String  specVersion, String  specVendor, String  implTitle, String  implVersion, String  implVendor, URL  sealBase)
      通过 name 在此 ClassLoader 中定义一个包。

      包名 在类加载器中必须是唯一的,并且一旦创建就不能重新定义或更改。

      如果类加载器希望定义具有特定属性(例如版本信息)的包,则类加载器应在调用 defineClass 之前调用此 definePackage 方法。否则,defineClass 方法会在这个类加载器中定义一个包对应新定义类的包;此定义包的属性由 Package 指定。

      API 注意:
      希望为 JAR 中的类定义包的类加载器通常使用 JAR 清单中的规范和实现标题、版本和供应商。如果包在 JAR 的清单中指定为 密封,则 JAR 文件的 URL 通常用作 sealBase。如果此类加载器定义的包 'p' 的类是从多个 JAR 加载的,则 Package 对象可能包含不同的信息,具体取决于定义的包 'p' 的第一个类以及首先读取哪个 JAR 的清单以显式定义包 'p'

      强烈建议类加载器不要调用此方法在 named modules 中显式定义包;相反,当一个类是 被定义 时,包将被自动定义。如果需要显式定义 Package,则应确保命名模块中的所有包都使用 Package 指定的属性进行定义。否则,命名模块中的某些 Package 对象可能会使用不同的密封基进行密封。

      参数:
      name - 包名字
      specTitle - 规范标题
      specVersion - 规范版本
      specVendor - 规范供应商
      implTitle - 实施标题
      implVersion - 实现版本
      implVendor - 实施供应商
      sealBase - 如果不是 null ,则此包相对于给定的代码源 URL 对象是密封的。否则,包装不密封。
      返回:
      新定义的 Package 对象
      抛出:
      NullPointerException - 如果 namenull
      IllegalArgumentException - 如果给定的 name 的包已经被此类加载器定义
      Java 虚拟机规范:
      5.3 创建和加载
      自从:
      1.2
      参见:
    • getDefinedPackage

      public final   getDefinedPackage(String  name)
      返回已由此类加载器定义的给定 namePackage
      参数:
      name - 包名字
      返回:
      已由此类加载器定义的给定名称的 Package,如果未找到,则为 null
      抛出:
      NullPointerException - 如果 namenull
      Java 虚拟机规范:
      5.3 创建和加载
      自从:
      9
    • getDefinedPackages

      public final  [] getDefinedPackages()
      返回已由此类加载器定义的所有 Package 。返回的数组没有重复的同名 Package
      API 注意:
      为了与现有的 getPackages() 方法保持一致,此方法返回一个数组而不是 SetStream
      返回:
      该类加载器定义的Package对象数组;如果此类加载器没有定义包,则为零长度数组。
      Java 虚拟机规范:
      5.3 创建和加载
      自从:
      9
    • getPackage

      @Deprecated (since ="9") protected   getPackage(String  name)
      已弃用。
      如果多个类加载器相互委托并定义具有相同包名的类,并且一个这样的加载器依赖于 getPackage 的查找行为从父加载器返回一个 Package,那么 Package 公开的属性可能与预期的不同程序的其余部分。例如,Package 只会公开父加载器定义的 package-info.class 文件中的注释,即使子加载器定义的 package-info.class 文件中存在注释。一种更健壮的方法是使用 getDefinedPackage(java.lang.String) 方法,它为指定的类加载器返回一个 Package
      在此类加载器及其祖先中查找 name 的包。

      如果此类加载器定义了给定名称的 Package,则返回 Package。否则,递归地(逐父)搜索此类加载器的祖先以查找给定名称的Package

      API 注意:
      platform class loader 可以委托给应用程序类加载器,但应用程序类加载器不是它的祖先。当在平台类加载器上调用时,此方法将找不到定义给应用程序类加载器的包。
      参数:
      name - 包名字
      返回:
      已由此类加载器或其祖先定义的给定名称的 Package,如果未找到,则为 null
      抛出:
      NullPointerException - 如果 namenull
      自从:
      1.2
      参见:
    • getPackages

      protected  [] getPackages()
      返回已由此类加载器及其祖先定义的所有 Package 。返回的数组可能包含多个具有相同包名的 Package 对象,每个对象由类加载器层次结构中的不同类加载器定义。
      API 注意:
      platform class loader 可以委托给应用程序类加载器。换句话说,定义给应用程序类加载器的模块中的包可能对平台类加载器可见。另一方面,应用程序类加载器不是它的祖先,因此当在平台类加载器上调用时,此方法不会返回任何定义给应用程序类加载器的包。
      返回:
      已由此类加载器及其祖先定义的 Package 对象数组
      自从:
      1.2
      参见:
    • findLibrary

      protected String  findLibrary(String  libname)
      返回本机库的绝对路径名。 VM 调用此方法来定位属于使用此类加载器加载的类的本机库。如果此方法返回 null ,VM 将沿着指定为“java.library.path”属性的路径搜索库。
      参数:
      libname - 图书馆名称
      返回:
      原生库的绝对路径
      自从:
      1.2
      参见:
    • setDefaultAssertionStatus

      public void setDefaultAssertionStatus(boolean enabled)
      设置此类加载器的默认断言状态。此设置确定由此类加载器加载并在将来初始化的类是否默认启用或禁用断言。可以通过调用 setPackageAssertionStatus(String, boolean) setClassAssertionStatus(String, boolean) 在每个包或每个类的基础上覆盖此设置。
      参数:
      enabled - true 如果由此类加载器加载的类此后默认启用断言,false 如果它们默认禁用断言。
      自从:
      1.4
    • setPackageAssertionStatus

      public void setPackageAssertionStatus(String  packageName, boolean enabled)
      为指定包设置包默认断言状态。包默认断言状态决定了未来初始化的属于指定包或其任何“子包”的类的断言状态。

      名为 p 的包的子包是名称以“p.”开头的任何包。例如javax.swing.textjavax.swing的子包,java.utiljava.lang.reflect都是java的子包。

      如果多个包默认值适用于给定的类,则与最具体的包相关的包默认值优先于其他包。例如,如果 javax.langjavax.lang.reflect 都有与其关联的包默认值,则后者包默认值适用于 javax.lang.reflect 中的类。

      包默认值优先于类加载器的默认断言状态,并且可以通过调用 setClassAssertionStatus(String, boolean) 在每个类的基础上被覆盖。

      参数:
      packageName - 要设置其包默认断言状态的包的名称。 null 值表示“当前”的未命名包(请参阅第 7.4.2Java 语言规范.)
      enabled - true 如果由该类加载器加载并属于指定包或其任何子包的类默认启用断言,false 如果它们默认禁用断言。
      自从:
      1.4
    • setClassAssertionStatus

      public void setClassAssertionStatus(String  className, boolean enabled)
      为此类加载器中的命名顶级类和其中包含的任何内部类设置所需的断言状态。此设置优先于类加载器的默认断言状态,以及任何适用的每个包默认设置。如果命名类已经初始化,则此方法无效。 (一旦一个类被初始化,它的断言状态就不能改变。)

      如果命名类不是顶级类,则此调用将不会影响任何类的实际断言状态。

      参数:
      className - 要设置其断言状态的顶级类的完全限定类名。
      enabled - true 如果指定的类在初始化时(以及如果)启用断言,false 如果类要禁用断言。
      自从:
      1.4
    • clearAssertionStatus

      public void clearAssertionStatus()
      将此类加载器的默认断言状态设置为 false 并丢弃与类加载器关联的任何包默认值或类断言状态设置。提供此方法是为了使类加载器可以忽略任何命令行或持久断言状态设置并“从头开始”。
      自从:
      1.4