- 已知子类:
SecureClassLoader
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
- 参见:
-
构造方法总结
构造方法修饰符构造方法描述protected
使用方法getSystemClassLoader()
返回的ClassLoader
创建一个新的类加载器作为父类加载器。protected
ClassLoader
(ClassLoader parent) 使用指定的父类加载器创建一个新的类加载器进行委托。protected
ClassLoader
(String name, ClassLoader parent) 创建指定名称的新类加载器并使用指定的父类加载器进行委托。 -
方法总结
修饰符和类型方法描述void
将此类加载器的默认断言状态设置为false
并丢弃与类加载器关联的任何包默认值或类断言状态设置。protected final Class<?>
defineClass
(byte[] b, int off, int len) 已弃用。protected final Class<?>
defineClass
(String name, byte[] b, int off, int len) 将字节数组转换为类Class
的实例。protected final Class<?>
defineClass
(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) 使用给定的ProtectionDomain
将字节数组转换为类Class
的实例。protected final Class<?>
defineClass
(String name, ByteBuffer b, ProtectionDomain protectionDomain) protected Package
definePackage
(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) 通过 name 在此ClassLoader
中定义一个包。protected Class<?>
查找具有指定 二进制名称 的类。protected Class<?>
在为此类加载器定义的模块中查找具有给定 二进制名称 的类。protected String
findLibrary
(String libname) 返回本机库的绝对路径名。protected final Class<?>
findLoadedClass
(String name) protected URL
findResource
(String name) 查找具有给定名称的资源。protected URL
findResource
(String moduleName, String name) 返回指向此类加载器定义的模块中资源的 URL。protected Enumeration<URL>
findResources
(String name) 返回代表具有给定名称的所有资源的URL
对象的枚举。protected final Class<?>
findSystemClass
(String name) 查找具有指定 二进制名称 的类,必要时加载它。protected Object
getClassLoadingLock
(String className) 返回类加载操作的锁对象。final Package
getDefinedPackage
(String name) 返回已由此类加载器定义的给定 name 的Package
。final Package[]
返回已由此类加载器定义的所有Package
。getName()
返回此类加载器的名称,如果未命名此类加载器,则返回null
。protected Package
getPackage
(String name) 已弃用。如果多个类加载器相互委托并定义具有相同包名的类,并且一个这样的加载器依赖于getPackage
的查找行为从父加载器返回一个Package
,那么Package
公开的属性可能与预期的不同程序的其余部分。protected Package[]
返回已由此类加载器及其祖先定义的所有Package
。final ClassLoader
返回委托的父类加载器。static ClassLoader
返回平台类加载器。getResource
(String name) 查找具有给定名称的资源。getResourceAsStream
(String name) 返回用于读取指定资源的输入流。getResources
(String name) 查找具有给定名称的所有资源。static ClassLoader
返回系统类加载器。static URL
getSystemResource
(String name) 从用于加载类的搜索路径中查找指定名称的资源。static InputStream
打开以供阅读,用于加载类的搜索路径中指定名称的资源。static Enumeration<URL>
getSystemResources
(String name) 从用于加载类的搜索路径中查找指定名称的所有资源。final Module
返回此类加载器的未命名Module
。final boolean
Class<?>
使用指定的 二进制名称 加载类。protected Class<?>
使用指定的 二进制名称 加载类。protected static boolean
将调用者注册为 并行能力 。protected final void
resolveClass
(Class<?> c) 链接指定的类。返回一个流,其元素是具有给定名称的所有资源的 URL。void
setClassAssertionStatus
(String className, boolean enabled) 为此类加载器中的命名顶级类和其中包含的任何内部类设置所需的断言状态。void
setDefaultAssertionStatus
(boolean enabled) 设置此类加载器的默认断言状态。void
setPackageAssertionStatus
(String packageName, boolean enabled) 为指定包设置包默认断言状态。protected final void
setSigners
(Class<?> c, Object[] signers) 设置类的签名者。
-
构造方法详细信息
-
ClassLoader
创建指定名称的新类加载器并使用指定的父类加载器进行委托。- API 注意:
-
如果父级指定为
null
(用于引导类加载器),则无法保证所有平台类都可见。 - 参数:
name
- 类加载器名称;或者null
如果没有命名parent
- 父类加载器- 抛出:
IllegalArgumentException
- 如果给定名称为空。SecurityException
- 如果安全管理器存在且其SecurityManager.checkCreateClassLoader()
方法不允许创建新的类加载器。- 自从:
- 9
-
ClassLoader
使用指定的父类加载器创建一个新的类加载器进行委托。如果有安全管理器,则调用其
checkCreateClassLoader
方法。这可能会导致安全异常。- API 注意:
-
如果父级指定为
null
(用于引导类加载器),则无法保证所有平台类都可见。 - 参数:
parent
- 父类加载器- 抛出:
SecurityException
- 如果安全管理器存在且其checkCreateClassLoader
方法不允许创建新的类加载器。- 自从:
- 1.2
-
ClassLoader
protected ClassLoader()使用方法getSystemClassLoader()
返回的ClassLoader
创建一个新的类加载器作为父类加载器。如果有安全管理器,则调用其
checkCreateClassLoader
方法。这可能会导致安全异常。- 抛出:
SecurityException
- 如果安全管理器存在且其checkCreateClassLoader
方法不允许创建新的类加载器。
-
-
方法详情
-
getName
返回此类加载器的名称,如果未命名此类加载器,则返回null
。- API 注意:
- 此方法不是最终的兼容性。如果重写此方法,则此方法必须返回与实例化此类加载器时指定的名称相同的名称。
- 返回:
-
此类加载器的名称;或者
null
如果这个类加载器没有命名。 - 自从:
- 9
-
loadClass
使用指定的 二进制名称 加载类。此方法以与loadClass(String, boolean)
方法相同的方式搜索类。 Java 虚拟机调用它来解析类引用。调用此方法等同于调用loadClass(name, false)
。- 参数:
name
- 类的 二进制名称- 返回:
-
生成的
Class
对象 - 抛出:
ClassNotFoundException
- 如果找不到该类
-
loadClass
使用指定的 二进制名称 加载类。此方法的默认实现按以下顺序搜索类:调用
findLoadedClass(String)
检查类是否已经加载。在父类加载器上调用
loadClass
方法。如果父级是null
,则使用虚拟机内置的类加载器。调用
findClass(String)
方法来查找类。
如果使用上述步骤找到该类,并且
resolve
标志为真,则此方法将在生成的Class
对象上调用resolveClass(Class)
方法。鼓励
ClassLoader
的子类覆盖findClass(String)
,而不是这个方法。除非被重写,否则此方法会在整个类加载过程中同步
getClassLoadingLock
方法的结果。- 参数:
name
- 类的 二进制名称resolve
- 如果true
然后解析类- 返回:
-
生成的
Class
对象 - 抛出:
ClassNotFoundException
- 如果找不到该类
-
getClassLoadingLock
返回类加载操作的锁对象。为了向后兼容,此方法的默认实现行为如下。如果此 ClassLoader 对象注册为具有并行能力,则该方法返回与指定类名关联的专用对象。否则,该方法返回此 ClassLoader 对象。- 参数:
className
- 待加载类的名称- 返回:
- 类加载操作的锁
- 抛出:
NullPointerException
- 如果注册为支持并行且className
为空- 自从:
- 1.7
- 参见:
-
findClass
- 实现要求:
-
默认实现抛出
ClassNotFoundException
。 - 参数:
name
- 类的 二进制名称- 返回:
-
生成的
Class
对象 - 抛出:
ClassNotFoundException
- 如果找不到该类- 自从:
- 1.2
-
findClass
在为此类加载器定义的模块中查找具有给定 二进制名称 的类。支持从模块加载的类加载器实现应该覆盖此方法。- API 注意:
-
如果找不到该类,此方法将返回
null
而不是抛出ClassNotFoundException
。 - 实现要求:
-
当
moduleName
为null
时,默认实现尝试通过调用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 - 参数:
b
- 构成类数据的字节。位置off
到off+len-1
中的字节应具有由定义的有效类文件的格式Java 虚拟机规范.off
- 类数据的b
中的起始偏移量len
- 类数据的长度- 返回:
-
从指定类数据创建的
Class
对象 - 抛出:
ClassFormatError
- 如果数据不包含有效类IndexOutOfBoundsException
- 如果off
或len
为负,或者如果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
- 构成类数据的字节。位置off
到off+len-1
中的字节应具有由定义的有效类文件的格式Java 虚拟机规范.off
- 类数据的b
中的起始偏移量len
- 类数据的长度- 返回:
-
从指定类数据创建的
Class
对象。 - 抛出:
ClassFormatError
- 如果数据不包含有效类IndexOutOfBoundsException
- 如果off
或len
为负,或者如果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
的实例。如果给定的
ProtectionDomain
是null
,则默认保护域将分配给defineClass(String, byte[], int, int)
文档中指定的类。在可以使用该类之前,必须对其进行解析。包中定义的第一个类确定了该包中定义的所有后续类必须包含的确切证书集。类的证书集是从类的
ProtectionDomain
中的CodeSource
获得的。添加到该包的任何类都必须包含相同的证书集,否则将抛出SecurityException
。请注意,如果name
是null
,则不会执行此检查。您应该始终传入您正在定义的类的 二进制名称 以及字节。这确保您定义的类确实是您认为的类。如果指定的
name
以“java.
”开头,则只能由平台类加载器或其祖先定义;否则将抛出SecurityException
。如果name
不是null
,它必须等于字节数组b
指定的类的 二进制名称,否则将抛出NoClassDefFoundError
。这个方法在这个类加载器中定义了一个对应于
Class
包的包(如果这个类加载器中还没有定义这样的包)。定义包的名称是从字节数组b
指定的类的二进制名称派生的。定义包的其他属性由Package
指定。- 参数:
name
- 类的预期 二进制名称,如果未知则为null
b
- 构成类数据的字节。位置off
到off+len-1
中的字节应具有由定义的有效类文件的格式Java 虚拟机规范.off
- 类数据的b
中的起始偏移量len
- 类数据的长度protectionDomain
- 类的ProtectionDomain
- 返回:
-
从数据创建的
Class
对象,以及ProtectionDomain
。 - 抛出:
ClassFormatError
- 如果数据不包含有效类NoClassDefFoundError
- 如果name
不是null
且不等于b
指定的类的 二进制名称IndexOutOfBoundsException
- 如果off
或len
为负,或者如果off+len
大于b.length
。SecurityException
- 如果尝试将此类添加到包含由与此类不同的一组证书签名的类的包中,或者如果name
以“java.
”开头并且此类加载器不是平台类加载器或其祖先。
-
defineClass
protected final Class <?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain) throws ClassFormatError 使用给定的ProtectionDomain
将ByteBuffer
转换为类Class
的实例。如果给定的ProtectionDomain
是null
,则默认保护域将分配给defineClass(String, byte[], int, int)
文档中指定的类。在可以使用该类之前,必须对其进行解析。关于包中定义的第一个类确定包的证书集、类名称的限制以及类的定义包的规则与
defineClass(String, byte[], int, int, ProtectionDomain)
的文档中指定的规则相同。调用此表单方法氯
.defineClass(
name,
b缓冲区,
PD)
产生与语句完全相同的结果...
byte[] temp = new byte[bBuffer.remaining
()];
bBuffer.get
(temp);
returncl.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
链接指定的类。这个(误导性命名的)方法可能被类加载器用来链接一个类。如果类c
已经被链接,那么这个方法简单地返回。否则,该类将按照“执行”一章中的描述进行链接Java 语言规范.- 参数:
c
- 要链接的类- 抛出:
NullPointerException
- 如果c
是null
。- 参见:
-
findSystemClass
查找具有指定 二进制名称 的类,必要时加载它。此方法通过系统类加载器加载类(请参阅
getSystemClassLoader()
)。返回的Class
对象可能关联了多个ClassLoader
。ClassLoader
的子类通常不需要调用此方法,因为大多数类加载器只需要覆盖findClass(String)
。- 参数:
name
- 类的 二进制名称- 返回:
-
指定
name
的Class
对象 - 抛出:
ClassNotFoundException
- 如果找不到该类- 参见:
-
findLoadedClass
- 参数:
name
- 类的 二进制名称- 返回:
Class
对象,或null
(如果类尚未加载)- 自从:
- 1.1
-
setSigners
设置类的签名者。这应该在定义一个类之后调用。- 参数:
c
-Class
对象signers
- 类的签名者- 自从:
- 1.1
-
findResource
返回指向此类加载器定义的模块中资源的 URL。支持从模块加载的类加载器实现应该重写此方法。- API 注意:
-
此方法是
Class.getResource
、Class.getResourceAsStream
和Module.getResourceAsStream
方法的基础。它不受Module.getResourceAsStream
指定的封装规则的约束。 - 实现要求:
-
当
moduleName
为null
时,默认实现尝试通过调用findResource(String)
来查找资源。否则返回null
。 - 参数:
moduleName
- 模块名称;或null
在 未命名模块 中为此类加载器查找资源name
- 资源名称- 返回:
-
资源的 URL;
null
如果找不到资源,则无法构造 URL 来定位资源,安全管理器拒绝访问资源,或者没有为类加载器定义给定名称的模块。 - 抛出:
IOException
- 如果发生 I/O 错误- 自从:
- 9
- 参见:
-
getResource
查找具有给定名称的资源。资源是一些数据(图像、音频、文本等),可以通过类代码以独立于代码位置的方式访问。资源的名称是标识资源的以“
/
”分隔的路径名。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包为opened
时无条件地在命名模块的包中查找资源(即使此方法的调用者在同一模块中作为资源)。- API 注意:
-
如果多个模块被定义到同一个类加载器,并且多个模块包含具有给定名称的资源,则搜索模块的顺序未指定并且可能非常不可预测。覆盖此方法时,建议实现确保任何委托与
getResources(String)
方法一致。 - 实现要求:
-
默认实现会先在父类加载器中搜索资源;如果父级是
null
,则搜索虚拟机中内置的类加载器的路径。如果未找到,此方法将调用findResource(String)
来查找资源。 - 参数:
name
- 资源名称- 返回:
URL
用于读取资源的对象;null
如果找不到资源,则无法构造URL
来定位资源,资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。- 抛出:
NullPointerException
- 如果name
是null
- 自从:
- 1.1
-
getResources
查找具有给定名称的所有资源。资源是一些数据(图像、音频、文本等),可以通过类代码以独立于代码位置的方式访问。资源的名称是标识资源的
/
分隔路径名。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包为opened
时无条件地在命名模块的包中查找资源(即使此方法的调用者在同一模块中作为资源)。- API 注意:
-
如果多个模块被定义到同一个类加载器,并且多个模块包含具有给定名称的资源,则没有指定顺序并且可能非常不可预测。覆盖此方法时,建议实现确保任何委托与
getResource(String)
方法一致。这应确保枚举的nextElement
方法返回的第一个元素与getResource(String)
方法将返回的资源相同。 - 实现要求:
-
默认实现会先在父类加载器中搜索资源;如果父级是
null
,则搜索虚拟机中内置的类加载器的路径。然后它调用findResources(String)
以在此类加载器中查找具有该名称的资源。它返回一个枚举,其元素是通过搜索父类加载器找到的 URL,然后是使用findResources
找到的元素。 - 参数:
name
- 资源名称- 返回:
-
资源的
URL
对象枚举。如果找不到资源,枚举将为空。无法构造URL
的资源位于未无条件打开的包中,或者安全管理器拒绝访问资源,不会在枚举中返回。 - 抛出:
IOException
- 如果发生 I/O 错误NullPointerException
- 如果name
是null
- 自从:
- 1.2
-
resources
返回一个流,其元素是具有给定名称的所有资源的 URL。资源是一些数据(图像、音频、文本等),可以通过类代码以独立于代码位置的方式访问。资源的名称是标识资源的
/
分隔路径名。评估返回的流时将定位资源。如果计算结果为
IOException
,则 I/O 异常被包装在UncheckedIOException
中,然后被抛出。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包为opened
时无条件地在命名模块的包中查找资源(即使此方法的调用者在同一模块中作为资源)。- API 注意:
-
覆盖此方法时,建议实现确保任何委托与
getResource(String)
方法一致。这应确保流返回的第一个元素与getResource(String)
方法将返回的资源相同。 - 实现要求:
-
默认实现调用
getResources
来查找具有给定名称的所有资源,并返回一个以枚举中的元素作为源的流。 - 参数:
name
- 资源名称- 返回:
-
资源
URL
对象流。如果找不到资源,则流将为空。无法构造URL
的资源,位于未无条件打开的包中,或者安全管理器拒绝访问资源,将不会在流中。 - 抛出:
NullPointerException
- 如果name
是null
- 自从:
- 9
-
findResource
查找具有给定名称的资源。类加载器实现应该重写这个方法。对于命名模块中的资源,该方法必须实施
Module
getResourceAsStream
方法中指定的封装规则。此外,它不能在命名模块的包中找到非“.class
”资源,除非包是无条件的opened
。- 实现要求:
-
默认实现返回
null
。 - 参数:
name
- 资源名称- 返回:
URL
用于读取资源的对象;null
如果找不到资源,则无法构造URL
来定位资源,资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。- 自从:
- 1.2
-
findResources
返回代表具有给定名称的所有资源的URL
对象的枚举。类加载器实现应该覆盖这个方法。对于命名模块中的资源,该方法必须实施
Module
getResourceAsStream
方法中指定的封装规则。此外,它不能在命名模块的包中找到非“.class
”资源,除非包是无条件的opened
。- 实现要求:
- 默认实现返回一个不包含任何元素的枚举。
- 参数:
name
- 资源名称- 返回:
-
资源的
URL
对象枚举。如果找不到资源,枚举将为空。无法构造URL
的资源位于未无条件打开的包中,或者安全管理器拒绝访问资源,不会在枚举中返回。 - 抛出:
IOException
- 如果发生 I/O 错误- 自从:
- 1.2
-
registerAsParallelCapable
protected static boolean registerAsParallelCapable()将调用者注册为 并行能力 。注册成功当且仅当满足以下所有条件:- 没有创建调用者的实例
- 调用者的所有超类(类 Object 除外)都注册为具有并行能力
请注意,一旦类加载器注册为具有并行能力,就无法将其更改回来。
如果此方法是从调用者不是
ClassLoader
的子类或堆栈上没有调用者框架的上下文调用的(例如,当直接从 JNI 附加线程调用时),则抛出IllegalCallerException
。- 返回:
true
如果调用者成功注册为具有并行能力,否则为false
。- 抛出:
IllegalCallerException
- 如果调用者不是ClassLoader
的子类- 自从:
- 1.7
- 参见:
-
isRegisteredAsParallelCapable
public final boolean isRegisteredAsParallelCapable()- 返回:
true
如果此类加载器具有并行能力,否则false
。- 自从:
- 9
- 参见:
-
getSystemResource
从用于加载类的搜索路径中查找指定名称的资源。该方法通过系统类加载器定位资源(参见getSystemClassLoader()
)。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包无条件为opened
时在命名模块的包中查找资源。- 参数:
name
- 资源名称- 返回:
URL
到资源;null
如果找不到资源,无法构造 URL 来定位资源,资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。- 自从:
- 1.1
-
getSystemResources
从用于加载类的搜索路径中查找指定名称的所有资源。这样找到的资源将作为Enumeration
个对象中的URL
个对象返回。getSystemResource(String)
的文档中描述了搜索顺序。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包无条件为opened
时在命名模块的包中查找资源。- 参数:
name
- 资源名称- 返回:
-
资源的
URL
对象枚举。如果找不到资源,枚举将为空。无法构造URL
的资源位于未无条件打开的包中,或者安全管理器拒绝访问资源,不会在枚举中返回。 - 抛出:
IOException
- 如果发生 I/O 错误- 自从:
- 1.2
-
getResourceAsStream
返回用于读取指定资源的输入流。getResource(String)
的文档中描述了搜索顺序。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包无条件为opened
时在命名模块的包中查找资源。- 参数:
name
- 资源名称- 返回:
-
用于读取资源的输入流;
null
如果找不到资源,则资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。 - 抛出:
NullPointerException
- 如果name
是null
- 自从:
- 1.1
-
getSystemResourceAsStream
打开以供阅读,用于加载类的搜索路径中指定名称的资源。该方法通过系统类加载器定位资源(参见getSystemClassLoader()
)。命名模块中的资源受
Module.getResourceAsStream
指定的封装规则的约束。此外,除了资源名称以“.class
”结尾的特殊情况外,此方法只会在包无条件为opened
时在命名模块的包中查找资源。- 参数:
name
- 资源名称- 返回:
-
用于读取资源的输入流;
null
如果找不到资源,则资源位于未无条件打开的包中,或者安全管理器拒绝访问资源。 - 自从:
- 1.1
-
getParent
返回委托的父类加载器。一些实现可能使用null
来表示引导类加载器。如果此类加载器的父类是引导类加载器,则此方法将在此类实现中返回null
。- 返回:
-
父母
ClassLoader
- 抛出:
SecurityException
- 如果存在安全管理器,并且调用者的类加载器不是null
并且不是此类加载器的祖先,并且调用者没有RuntimePermission
("getClassLoader")
- 自从:
- 1.2
-
getUnnamedModule
返回此类加载器的未命名Module
。- 返回:
- 此类加载器的未命名模块
- 自从:
- 9
- 参见:
-
getPlatformClassLoader
返回平台类加载器。所有 平台类 对平台类加载器都是可见的。- 实现注意事项:
-
内置平台类加载器的名称是
"platform"
。 - 返回:
-
平台
ClassLoader
。 - 抛出:
SecurityException
- 如果存在安全管理器,并且调用者的类加载器不是null
,并且调用者的类加载器与平台类加载器不同或不是平台类加载器的祖先,并且调用者没有RuntimePermission
("getClassLoader")
- 自从:
- 9
-
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
- 如果name
是null
。IllegalArgumentException
- 如果给定的name
的包已经被此类加载器定义- 看Java 虚拟机规范:
-
5.3 创建和加载
- 自从:
- 1.2
- 参见:
-
getDefinedPackage
返回已由此类加载器定义的给定 name 的Package
。- 参数:
name
- 包名字- 返回:
-
已由此类加载器定义的给定名称的
Package
,如果未找到,则为null
- 抛出:
NullPointerException
- 如果name
是null
。- 看Java 虚拟机规范:
-
5.3 创建和加载
- 自从:
- 9
-
getDefinedPackages
返回已由此类加载器定义的所有Package
。返回的数组没有重复的同名Package
。- API 注意:
-
为了与现有的
getPackages()
方法保持一致,此方法返回一个数组而不是Set
或Stream
。 - 返回:
-
该类加载器定义的
Package
对象数组;如果此类加载器没有定义包,则为零长度数组。 - 看Java 虚拟机规范:
-
5.3 创建和加载
- 自从:
- 9
-
getPackage
已弃用。如果多个类加载器相互委托并定义具有相同包名的类,并且一个这样的加载器依赖于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
- 如果name
是null
。- 自从:
- 1.2
- 参见:
-
getPackages
返回已由此类加载器及其祖先定义的所有Package
。返回的数组可能包含多个具有相同包名的Package
对象,每个对象由类加载器层次结构中的不同类加载器定义。- API 注意:
platform class loader
可以委托给应用程序类加载器。换句话说,定义给应用程序类加载器的模块中的包可能对平台类加载器可见。另一方面,应用程序类加载器不是它的祖先,因此当在平台类加载器上调用时,此方法不会返回任何定义给应用程序类加载器的包。- 返回:
-
已由此类加载器及其祖先定义的
Package
对象数组 - 自从:
- 1.2
- 参见:
-
findLibrary
返回本机库的绝对路径名。 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
为指定包设置包默认断言状态。包默认断言状态决定了未来初始化的属于指定包或其任何“子包”的类的断言状态。名为 p 的包的子包是名称以“
p.
”开头的任何包。例如javax.swing.text
是javax.swing
的子包,java.util
和java.lang.reflect
都是java
的子包。如果多个包默认值适用于给定的类,则与最具体的包相关的包默认值优先于其他包。例如,如果
javax.lang
和javax.lang.reflect
都有与其关联的包默认值,则后者包默认值适用于javax.lang.reflect
中的类。包默认值优先于类加载器的默认断言状态,并且可以通过调用
setClassAssertionStatus(String, boolean)
在每个类的基础上被覆盖。- 参数:
packageName
- 要设置其包默认断言状态的包的名称。null
值表示“当前”的未命名包(请参阅第 7.4.2 节Java 语言规范.)enabled
-true
如果由该类加载器加载并属于指定包或其任何子包的类默认启用断言,false
如果它们默认禁用断言。- 自从:
- 1.4
-
setClassAssertionStatus
为此类加载器中的命名顶级类和其中包含的任何内部类设置所需的断言状态。此设置优先于类加载器的默认断言状态,以及任何适用的每个包默认设置。如果命名类已经初始化,则此方法无效。 (一旦一个类被初始化,它的断言状态就不能改变。)如果命名类不是顶级类,则此调用将不会影响任何类的实际断言状态。
- 参数:
className
- 要设置其断言状态的顶级类的完全限定类名。enabled
-true
如果指定的类在初始化时(以及如果)启用断言,false
如果类要禁用断言。- 自从:
- 1.4
-
clearAssertionStatus
public void clearAssertionStatus()将此类加载器的默认断言状态设置为false
并丢弃与类加载器关联的任何包默认值或类断言状态设置。提供此方法是为了使类加载器可以忽略任何命令行或持久断言状态设置并“从头开始”。- 自从:
- 1.4
-
defineClass(String, byte[], int, int)