所有类


java.lang
类 ClassLoader

java.lang.Object
  继承者 java.lang.ClassLoader
直接已知子类:
SecureClassLoader

public abstract class ClassLoader
   
   
   
   
   
extends Object

类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。

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

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

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

类加载器通常由安全管理器使用,用于指示安全域。

ClassLoader 类使用委托模型来搜索类和资源。每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器。

通常情况下,Java 虚拟机以与平台有关的方式,从本地文件系统中加载类。例如,在 UNIX 系统中,虚拟机从 CLASSPATH 环境变量定义的目录中加载类。

然而,有些类可能并非源自一个文件;它们可能源自其他来源(如网络),也可能是由应用程序构造的。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) {
             // load the class data from the connection
              . . .
         }
     }
 

二进制名称

按照《Java Language Specification》的定义,任何作为 String 类型参数传递给 ClassLoader 中方法的类名称都必须是一个二进制名称。

有效类名称的示例包括:

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

从以下版本开始:
1.0
另请参见:
resolveClass(Class)

构造方法摘要
protected ClassLoader()
          使用方法 getSystemClassLoader() 返回的 ClassLoader 创建一个新的类加载器,将该加载器作为父类加载器。
protected ClassLoader(ClassLoader parent)
          使用指定的、用于委托操作的父类加载器创建新的类加载器。
 
方法摘要
 void clearAssertionStatus()
          将此类加载器的默认断言状态设置为 false,并放弃与此类加载器关联的所有默认包或类断言状态设置。
protected  Class<?> defineClass(byte[] b, int off, int len)
          已过时。 defineClass(String, byte[], int, int) 取代
protected  Class<?> defineClass(String name, byte[] b, int off, int len)
          将一个字节数组转换为 Class 类的实例。
protected  Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain)
          使用可选的 ProtectionDomain 将一个字节数组转换为 Class 类的实例。
protected  Class<?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain)
          使用可选的 ProtectionDomainByteBuffer 转换为 Class 类的实例。
protected  Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
          根据 name 在此 ClassLoader 中定义包。
protected  Class<?> findClass(String name)
          使用指定的二进制名称查找类。
protected  String findLibrary(String libname)
          返回本机库的绝对路径名。
protected  Class<?> findLoadedClass(String name)
          如果 Java 虚拟机已将此加载器记录为具有给定二进制名称的某个类的启动加载器,则返回该二进制名称的类。
protected  URL findResource(String name)
          查找具有给定名称的资源。
protected  Enumeration<URL> findResources(String name)
          返回表示所有具有给定名称的资源的 URL 对象的枚举。
protected  Class<?> findSystemClass(String name)
          查找具有指定的二进制名称的类,必要时加载它。
protected  Package getPackage(String name)
          返回由此类加载器或其任何祖先所定义的 Package
protected  Package[] getPackages()
          返回此类加载器及其祖先所定义的所有 Package
 ClassLoader getParent()
          返回委托的父类加载器。
 URL getResource(String name)
          查找具有给定名称的资源。
 InputStream getResourceAsStream(String name)
          返回读取指定资源的输入流。
 Enumeration<URL> getResources(String name)
          查找所有给定名称的资源。
static ClassLoader getSystemClassLoader()
          返回委托的系统类加载器。
static URL getSystemResource(String name)
          从用来加载类的搜索路径中查找具有指定名称的资源。
static InputStream getSystemResourceAsStream(String name)
          从用来加载类的搜索路径打开具有指定名称的资源,以读取该资源。
static Enumeration<URL> getSystemResources(String name)
          从用来加载类的搜索路径中查找所有具有指定名称的资源。
 Class<?> loadClass(String name)
          使用指定的二进制名称来加载类。
protected  Class<?> loadClass(String name, boolean resolve)
          使用指定的二进制名称来加载类。
protected  void resolveClass(Class<?> c)
          链接指定的类。
 void setClassAssertionStatus(String className, boolean enabled)
          设置在此类加载器及其包含的嵌套类中指定的最高层类所需的断言状态。
 void setDefaultAssertionStatus(boolean enabled)
          设置此类加载器的默认断言状态。
 void setPackageAssertionStatus(String packageName, boolean enabled)
          为指定包设置默认断言状态。
protected  void setSigners(Class<?> c, Object[] signers)
          设置类的签署者。
 
从类 java.lang.Object 继承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

构造方法详细信息

ClassLoader

protected ClassLoader(ClassLoader parent)
使用指定的、用于委托操作的父类加载器创建新的类加载器。

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

参数:
parent - 父类加载器
抛出:
SecurityException - 如果存在安全管理器并且其 checkCreateClassLoader 方法不允许创建新的类加载器。
从以下版本开始:
1.2

ClassLoader

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

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

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

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),而不是使用此方法。

参数:
name - 类的二进制名称
resolve - 如果该参数为 true,则分析这个类
返回:
得到的 Class 对象
抛出:
ClassNotFoundException - 如果无法找到类

findClass

protected Class<?> findClass(String name)
                      throws ClassNotFoundException
使用指定的二进制名称查找类。此方法应该被类加载器的实现重写,该实现按照委托模型来加载类。在通过父类加载器检查所请求的类后,此方法将被 loadClass 方法调用。默认实现抛出一个 ClassNotFoundException

参数:
name - 类的二进制名称
返回:
得到的 Class 对象
抛出:
ClassNotFoundException - 如果无法找到类
从以下版本开始:
1.2

defineClass

@Deprecated
protected final Class<?> defineClass(byte[] b,
                                                int off,
                                                int len)
                              throws ClassFormatError
已过时。 defineClass(String, byte[], int, int) 取代

将一个字节数组转换为 Class 类的实例。必须分析 Class,然后才能使用它。此方法已废弃,新版本将二进制名称作为该类的第一个参数,后者更加安全。

参数:
b - 组成类数据的字节。offoff+len-1 之间的字节应该具有《Java Virtual Machine Specification》定义的有效类文件的格式。
off - 类数据的 b 中的起始偏移量
len - 类数据的长度
返回:
从指定类数据创建的 Class 对象
抛出:
ClassFormatError - 如果数据不包含有效类
IndexOutOfBoundsException - 如果 offlen 为负,或者 off+len 大于 b.length
另请参见:
loadClass(String, boolean), resolveClass(Class)

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 分配给类,需要使用 defineClass 方法,该方法将 ProtectionDomain 用作其参数之一。

参数:
name - 所需要的类的二进制名称,如果不知道此名称,则该参数为 null
b - 组成类数据的字节。offoff+len-1 之间的字节应该具有《Java Virtual Machine Specification》定义的有效类文件的格式。
off - 类数据的 b 中的起始偏移量
len - 类数据的长度
返回:
从指定类数据中创建的 Class 对象。
抛出:
ClassFormatError - 如果数据不包含有效类
IndexOutOfBoundsException - 如果 offlen 为负,或者 off+len 大于 b.length
SecurityException - 如果试图将此类添加到包含由不同证书集签名的类(而不是此类,此类未签名)的包中,或者 name 以 "java." 开头。
从以下版本开始:
1.1
另请参见:
loadClass(String, boolean), resolveClass(Class), CodeSource, SecureClassLoader

defineClass

protected final Class<?> defineClass(String name,
                                     byte[] b,
                                     int off,
                                     int len,
                                     ProtectionDomain protectionDomain)
                              throws ClassFormatError
使用可选的 ProtectionDomain 将一个字节数组转换为 Class 类的实例。如果该域为 null,则将默认域分配给 defineClass(String, byte[], int, int) 的文档中指定的类。这个类必须分析后才能使用。

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

指定的 name 不能以 "java." 开头,因为 "java.*" 包中的所有类都只能由引导类加载器定义。如果 name 不是 null,则它必定等于由字节数组 "b" 指定的类的二进制名称,否则将抛出 NoClassDefFoundError

参数:
name - 所需类的二进制名称,如果不知道此名称,则该参数为 null
b - 组成类数据的字节。从 offoff+len-1 的字节应该具有由《Java Virtual Machine Specification》定义的有效类文件的格式。
off - 类数据的 b 中的起始偏移量
len - 类数据的长度
protectionDomain - 类的 ProtectionDomain
返回:
从数据中创建的 Class 对象和可选的 ProtectionDomain
抛出:
ClassFormatError - 如果数据不包含有效的类
NoClassDefFoundError - 如果 name 不等于 b 指定的类的二进制名称
IndexOutOfBoundsException - 如果 off 或者 len 为负,或者 off+len 大于 b.length
SecurityException - 如果试图将此类添加到某个包中,而这个包中包含由不同证书集合(而不是该类)签名的类,或者 name 以 "java." 开头。

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部