Module java.base
Package java.lang

Class ClassLoader

java.lang.Object
java.lang.ClassLoader
直接已知的子类:
SecureClassLoader

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

每个Class对象都包含一个指向定义它的ClassLoader引用

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

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

类加载器通常可被安全管理器用于指示安全域。

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

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

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

运行时内置类加载器

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

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

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

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

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

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

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

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

网络类加载器子类必须定义findClassloadClassData方法来从网络加载类。一旦下载构成类的字节,它应该使用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) {
             // 从连接中加载类数据
              . .
         }
     }
 

二进制名称

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

有效类名的示例包括:

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

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

参见Java语言规范
6.7 完全限定名称
13.1 二进制形式
自:
1.0
另请参见:
  • Constructor Details

    • 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方法不允许创建新的类加载器
  • Method Details

    • 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标志为true,则此方法将在结果Class对象上调用resolveClass(Class)方法。

      ClassLoader的子类鼓励重写findClass(String),而不是此方法。

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

      参数:
      name - 类的二进制名称
      resolve - 如果为true,则解析类
      返回:
      结果Class对象
      抛出:
      ClassNotFoundException - 如果找不到类
    • getClassLoadingLock

      protected Object getClassLoadingLock(String className)
      返回用于类加载操作的锁对象。
      API 注意:
      此方法允许并行可用的类加载器实现更细粒度的锁定方案,以便多个线程可以并发加载类而不会发生死锁。对于不支持并行的类加载器,类加载器对象在整个类加载操作期间都会同步。非层次委派的类加载器应该注册为并行可用以防止死锁。
      实现要求:
      如果此ClassLoader对象已注册为并行可用,则此方法返回与指定类名关联的专用对象。否则,此方法返回此ClassLoader对象。
      参数:
      className - 要加载的类的名称
      返回:
      类加载操作的锁
      抛出:
      NullPointerException - 如果已注册为并行可用且classNamenull
      自:
      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
      实现要求:
      默认实现尝试通过调用findClass(String)来查找类,当moduleNamenull时。否则返回null
      参数:
      moduleName - 模块名称;或者为null以在此类加载器的未命名模块中查找类
      name - 类的二进制名称
      返回:
      结果Class对象,如果找不到类则返回null
      自:
      9
    • defineClass

      @Deprecated(since="1.1") protected final Class<?> defineClass(byte[] b, int off, int len) throws ClassFormatError
      Deprecated.
      将字节数组转换为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。当调用Policy.getPolicy().getPermissions(new CodeSource(null, null))时,ProtectionDomain实际上被授予与返回的相同的权限集。默认的保护域是在第一次调用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
      将字节数组转换为带有给定ProtectionDomainClass类的实例。

      如果给定的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
      ByteBuffer转换为带有给定ProtectionDomainClass类的实例。如果给定的ProtectionDomainnull,则将根据defineClass(String, byte[], int, int)文档为类分配默认的保护域。在使用类之前,必须对其进行解析。

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

      cl.defineClass(name, bBuffer, 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 - 类的ProtectionDomain,或null
      返回:
      从数据创建的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对象可能与多个ClassLoader相关联。通常不需要子类化ClassLoader调用此方法,因为大多数类加载器只需要覆盖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.getResourceClass.getResourceAsStreamModule.getResourceAsStream方法的基础。它不受Module.getResourceAsStream指定的封装规则的约束。
      实现要求:
      默认实现尝试通过调用findResource(String)来查找资源,当moduleNamenull时。否则返回null
      参数:
      moduleName - 模块名称;或null以在此类加载器的未命名模块中查找资源
      name - 资源名称
      返回:
      资源的URL;如果找不到资源、无法构造URL以定位资源、安全管理器拒绝访问资源或没有为类加载器定义给定名称的模块,则返回null
      抛出:
      IOException - 如果发生I/O错误
      自版本:
      9
      参见:
    • getResource

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

      资源的名称是一个以'/'分隔的路径名,用于标识资源。

      命名模块中的资源受Module.getResourceAsStream指定的封装规则约束。此外,除了资源名称以".class"结尾的特殊情况外,此方法仅在包被无条件打开时才在命名模块的包中查找资源(即使调用此方法的调用者与资源所在的模块相同)。

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

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

      资源的名称是一个/分隔的路径名,用于标识资源。

      命名模块中的资源受Module.getResourceAsStream指定的封装规则约束。此外,除了资源名称以".class"结尾的特殊情况外,此方法仅在包被无条件打开时才在命名模块的包中查找资源(即使调用此方法的调用者与资源所在的模块相同)。

      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,则将在UncheckedIOException中包装I/O异常,然后抛出。

      命名模块中的资源受Module.getResourceAsStream指定的封装规则约束。此外,除非资源的名称以".class"结尾,否则此方法仅在命名模块的包中找到资源,当包无条件打开时(即使调用此方法的调用者与资源位于同一模块中)。

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

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

      对于命名模块中的资源,该方法必须实现Module getResourceAsStream方法中指定的封装规则。此外,除非资源的名称以".class"结尾,否则不应在命名模块的包中找到非".class"资源,除非该包无条件打开

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

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

      对于命名模块中的资源,该方法必须实现Module getResourceAsStream方法中指定的封装规则。此外,除非资源的名称以".class"结尾,否则不应在命名模块的包中找到非".class"资源,除非该包无条件打开

      实现要求:
      默认实现返回一个不包含元素的枚举。
      参数:
      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"结尾,否则此方法仅在命名模块的包中找到资源,当包无条件打开时。

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

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

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

      命名模块中的资源受Module.getResourceAsStream指定的封装规则约束。此外,除非资源的名称以".class"结尾,否则此方法仅在命名模块的包中找到资源,当包无条件打开时。

      参数:
      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
      返回:
      此类加载器的未命名 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 Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
      在此 ClassLoader 中按 名称 定义一个包。

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

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

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

      强烈建议类加载器不要调用此方法来显式定义在命名模块中的包;相反,当定义类时将自动定义包。如果希望显式定义Package,应确保所有命名模块中的包都使用Package指定的属性进行定义。否则,命名模块中的一些Package对象可能例如使用不同的seal base进行封装。

      参数:
      name - 包名称
      specTitle - 规范标题
      specVersion - 规范版本
      specVendor - 规范供应商
      implTitle - 实现标题
      implVersion - 实现版本
      implVendor - 实现供应商
      sealBase - 如果不为null,则该包将与给定代码源的URL对象相关联。否则,该包未封装。
      返回:
      新定义的Package对象
      抛出:
      NullPointerException - 如果namenull
      IllegalArgumentException - 如果给定name的包已由此类加载器定义
      参见 Java虚拟机规范:
      5.3 创建和加载
      自版本:
      1.2
      另请参阅:
    • getDefinedPackage

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

      public final Package[] getDefinedPackages()
      返回由此类加载器定义的所有Package。返回的数组中不包含相同名称的重复Package
      API 注释:
      为了与现有的getPackages()方法保持一致,此方法返回数组而不是SetStream
      返回:
      由此类加载器定义的Package对象数组;如果此类加载器未定义任何包,则返回长度为零的数组。
      参见 Java虚拟机规范:
      5.3 创建和加载
      自版本:
      9
    • getPackage

      @Deprecated(since="9") protected Package getPackage(String name)
      Deprecated.
      If multiple class loaders delegate to each other and define classes with the same package name, and one such loader relies on the lookup behavior of getPackage to return a Package from a parent loader, then the properties exposed by the Package may not be as expected in the rest of the program. For example, the Package will only expose annotations from the package-info.class file defined by the parent loader, even if annotations exist in a package-info.class file defined by a child loader. A more robust approach is to use the getDefinedPackage(java.lang.String) method which returns a Package for the specified class loader.
      在此类加载器及其祖先中按名称查找包。

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

      API 注释:
      平台类加载器可能委托给应用程序类加载器,但应用程序类加载器不是其祖先。在平台类加载器上调用此方法时,将不会找到定义为应用程序类加载器的包。
      参数:
      name - 包名称
      返回:
      由此类加载器或其祖先定义的给定名称的Package,如果未找到则返回null
      抛出:
      NullPointerException - 如果namenull
      自版本:
      1.2
      另请参阅:
    • getPackages

      protected Package[] getPackages()
      返回由此类加载器及其祖先定义的所有Package。返回的数组可能包含同一包名称的多个Package对象,每个由类加载器层次结构中的不同类加载器定义。
      API 注释:
      平台类加载器可能委托给应用程序类加载器。换句话说,定义为应用程序类加载器的模块中的包可能对平台类加载器可见。另一方面,应用程序类加载器不是其祖先,因此在平台类加载器上调用此方法时,将不会返回定义为应用程序类加载器的任何包。
      返回:
      由此类加载器及其祖先定义的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值表示"当前"的未命名包(请参阅The Java Language Specification的第7.4.2节)。
      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