public abstract class ClassLoader extends Object
每个类
对象包含reference
来定义它的ClassLoader。
类数组类的对象不是由类加载器创建的,而是按照Java运行时的要求自动创建的。 Class.getClassLoader()
返回的数组类的类加载器与其元素类型的类加载器相同; 如果元素类型是原始类型,则数组类没有类加载器。
应用程序实现ClassLoader的子类 ,以扩展Java虚拟机动态加载类的方式。
安全管理员通常可以使用类加载器来指示安全域。
ClassLoader类使用委托模式来搜索类和资源。 ClassLoader的每个实例都有一个关联的父类加载器。 当请求查找类或资源时, ClassLoader实例将在尝试查找类或资源本身之前将类或资源的搜索委托给其父类加载器。 虚拟机的内置类加载器(称为“引导类加载器”)本身不具有父级,但可以作为ClassLoader实例的父级。
支持并发加载类的类加载器称为并行能力类加载器,并且需要通过调用ClassLoader.registerAsParallelCapable
方法在其类初始化时间注册自身。 请注意,默认情况下, ClassLoader类注册为并行。 然而,它的子类仍然需要注册自己,如果它们是并行的能力。
在委托模式不是严格层次化的环境中,类加载器需要并行,否则加载类可能导致死锁,因为加载程序锁定在类加载过程中保持(参见loadClass
方法)。
通常,Java虚拟机以平台相关的方式从本地文件系统加载类。 例如,在UNIX系统上,虚拟机从CLASSPATH环境变量定义的目录加载类。
然而,一些类可能不是源于文件; 它们可以来自诸如网络的其他来源,或者它们可以由应用构建。 方法defineClass
将字节数组转换为类别类的实例。 这个新定义的类的实例可以使用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参数的方法必须是The Java™ Language Specification所定义的二进制名称。
有效的类名的示例包括:
"java.lang.String" "javax.swing.JSpinner$DefaultEditor" "java.security.KeyStore$Builder$FileBuilder$1" "java.net.URLClassLoader$3$1"
resolveClass(Class)
Modifier | Constructor and Description |
---|---|
protected |
ClassLoader()
创建使用该方法返回的
ClassLoader一个新的类加载器
getSystemClassLoader() 作为父类加载器。
|
protected |
ClassLoader(ClassLoader parent)
使用指定的父类加载器创建一个新的类加载器进行委派。
|
Modifier and Type | Method and Description |
---|---|
void |
clearAssertionStatus()
将此类加载器的默认断言状态设置为
false ,并丢弃与类加载器相关
联的任何包默认值或类断言状态设置。
|
protected 类<?> |
defineClass(byte[] b, int off, int len)
|
protected 类<?> |
defineClass(String name, byte[] b, int off, int len)
将字节数组转换为类别
类的实例。
|
protected 类<?> |
defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain)
将字节数组转换为类别
类的实例,其中可选的是
ProtectionDomain 。
|
protected 类<?> |
defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain)
一个转换 ByteBuffer 到类类的实例,带有可选ProtectionDomain。
|
protected 软件包 |
definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
在这个
ClassLoader中按名称定义一个包。
|
protected 类<?> |
findClass(String name)
找到具有指定的课程
binary name 。
|
protected String |
findLibrary(String libname)
返回本机库的绝对路径名。
|
protected 类<?> |
findLoadedClass(String name)
返回给定类
binary name如果装载机已记录由Java虚拟机作为与一类的初始化加载器
binary name 。
|
protected URL |
findResource(String name)
找到具有给定名称的资源。
|
protected Enumeration<URL> |
findResources(String name)
返回表示具有给定名称的所有资源的 URL 对象的枚举。
|
protected 类<?> |
findSystemClass(String name)
查找具有指定的类别
binary name ,如果需要加载它。
|
protected Object |
getClassLoadingLock(String className)
返回类加载操作的锁定对象。
|
protected 软件包 |
getPackage(String name)
返回已经被这个类加载器或其任何祖先所定义的
Package。
|
protected 软件包[] |
getPackages()
返回所有此类加载器及其祖先所定义的
Packages的。
|
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)
从用于加载类的搜索路径中查找指定名称的所有资源。
|
类<?> |
loadClass(String name)
用指定的binary name
加载课程 。
|
protected 类<?> |
loadClass(String name, boolean resolve)
加载类别与指定的
binary name 。
|
protected static boolean |
registerAsParallelCapable()
将呼叫者注册为并行功能。
|
protected void |
resolveClass(类<?> c)
链接指定的类。
|
void |
setClassAssertionStatus(String className, boolean enabled)
为此类加载器中指定的顶级类和其中包含的任何嵌套类设置所需的断言状态。
|
void |
setDefaultAssertionStatus(boolean enabled)
设置此类加载器的默认断言状态。
|
void |
setPackageAssertionStatus(String packageName, boolean enabled)
设置命名包的包默认断言状态。
|
protected void |
setSigners(类<?> c, Object[] signers)
设置一个类的签名者。
|
protected ClassLoader(ClassLoader parent)
如果有安全管理员,则调用其checkCreateClassLoader
方法。 这可能会导致安全例外。
parent
- 父类加载器
SecurityException
- 如果安全管理器存在,并且其
checkCreateClassLoader方法不允许创建新的类加载器。
protected ClassLoader()
getSystemClassLoader()
作为父类加载器。
如果有安全管理员,则调用其checkCreateClassLoader
方法。 这可能会导致安全例外。
SecurityException
- 如果安全管理器存在,并且其
checkCreateClassLoader方法不允许创建新的类加载器。
public 类<?> loadClass(String name) throws ClassNotFoundException
loadClass(String, boolean)
方法相同的方式搜索类。
它由Java虚拟机调用来解析类引用。
调用此方法相当于调用loadClass(name, false)
。
name
-
班级的binary name
ClassNotFoundException
- 如果没有找到该类
protected 类<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
调用findLoadedClass(String)
以检查类是否已经被加载。
在父类加载器上调用loadClass
方法。 如果父级是null ,则使用虚拟机内置的类加载器。
调用findClass(String)
方法来查找该类。
如果使用上述步骤发现的类和resolve标志为真,则此方法将然后调用resolveClass(Class)
所得类对象上的方法。
鼓励ClassLoader的子类覆盖findClass(String)
,而不是这种方法。
除非被覆盖,否则该方法在整个类加载过程中同步getClassLoadingLock
方法的结果。
name
-
班级的binary name
resolve
- 如果
true然后解决该类
ClassNotFoundException
- 如果找不到该类
protected Object getClassLoadingLock(String className)
className
- 要加载的类的名称
NullPointerException
- 如果注册为并行,
className为空
loadClass(String, boolean)
protected 类<?> findClass(String name) throws ClassNotFoundException
loadClass
方法调用。
默认实现会抛出一个ClassNotFoundException 。
name
-
班级的binary name
ClassNotFoundException
- 如果找不到该类
@Deprecated protected final 类<?> defineClass(byte[] b, int off, int len) throws ClassFormatError
b
- 构成类数据的字节。
位置off至off+len-1中的字节应具有由The Java™ Virtual Machine Specification定义的有效类文件的格式。
off
- 类数据中的起始偏移量为
b
len
- 类数据的长度
ClassFormatError
- 如果数据不包含有效的类
IndexOutOfBoundsException
- 如果
off或
len为负数,或
off+len是否大于
b.length 。
SecurityException
- 如果尝试将此类添加到包含由不同于该类的不同证书集签名的类的包中,或者尝试在具有完全限定名称的包中定义类时,以“
java.
”开头。
loadClass(String, boolean)
,
resolveClass(Class)
protected final 类<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError
此方法将默认的ProtectionDomain
分配给新定义的类。 该ProtectionDomain有效授予时相同的权限集返回Policy.getPolicy().getPermissions(new CodeSource(null, null))
被调用。 默认域是在首次调用defineClass
时创建的,并在以后的调用中重新使用。
要指定特定ProtectionDomain到类,使用defineClass
方法,它接受ProtectionDomain作为它的一个参数。
name
- 预期的
binary name的类,或
null如果不知道
b
- 构成类数据的字节。
位置off至off+len-1中的字节应具有由The Java™ Virtual Machine Specification定义的有效类文件的格式。
off
- 类数据中的起始偏移量为
b
len
- 类数据的长度
ClassFormatError
- 如果数据不包含有效的类
IndexOutOfBoundsException
- 如果
off或
len为负数,或
off+len是否大于
b.length 。
SecurityException
- 如果尝试将此类添加到包含由不同于该类(未签名)的不同证书集签名的包的包中,或者如果
name以“
java. ”开头。
loadClass(String, boolean)
, resolveClass(Class)
, CodeSource
, SecureClassLoader
protected final 类<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) throws ClassFormatError
defineClass(String, byte[], int, int)
。
在课堂可以使用之前,必须解决。
包中定义的第一个类决定了该包中定义的所有后续类必须包含的精确的证书集。 一套课程的证书是从班级ProtectionDomain中的CodeSource
获得的。 添加到该包中的任何类必须包含相同的证书集, 否则将抛出SecurityException 。 请注意,如果name为null ,则不执行此检查。 你应该总是传递你所定义的类的binary name以及字节。 这确保你所定义的类确实是你认为的类。
指定name不能以“java.”开始,因为在所有的类“java.*包只能由引导类装载程序来限定。如果name不是null,它必须等于binary name类的由字节数组指定” b “,否则将抛出一个NoClassDefFoundError
。
name
- 预期的
binary name的类,或
null如果不知道
b
- 构成类数据的字节。
位置8840509271767至off+len-1中的字节应具有由The Java™ Virtual Machine Specification定义的有效类文件的格式。
off
- 类数据中的起始偏移量为
b
len
- 类数据的长度
protectionDomain
- 该类的ProtectionDomain
ClassFormatError
- 如果数据不包含有效的类
NoClassDefFoundError
- 如果
name不等于
b指定的类别的
binary name
IndexOutOfBoundsException
- 如果
off或
len为负数,或
off+len是否大于
b.length 。
SecurityException
- 如果尝试将此类添加到包含由不同于该类的证书组签名的类的包中,或者如果
name以“
java. ”开头。
protected final 类<?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain) throws ClassFormatError
ByteBuffer
到类类的实例,带有可选ProtectionDomain。
如果域是null,则默认的域名将被作为文件规定分配给类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
- 预期binary name 。
的课程,或null如果不知道
b
- 构成类数据的字节。
来自位置b.position()至b.position() + b.limit() -1的字节应具有由The Java™ Virtual Machine Specification定义的有效类文件的格式。
protectionDomain
- 该类的ProtectionDomain,或
null 。
ClassFormatError
- 如果数据不包含有效的类。
NoClassDefFoundError
- 如果
name不等于
b指定的类别的
binary name
SecurityException
- 如果尝试将此类添加到包含由不同于该类的证书组签名的类的包中,或者如果
name以“
java. ”开头。
defineClass(String, byte[], int, int, ProtectionDomain)
protected final void resolveClass(类<?> c)
c
- 要链接的类
NullPointerException
- 如果
c是
null 。
defineClass(String, byte[], int, int)
protected final 类<?> findSystemClass(String name) throws ClassNotFoundException
该方法通过系统类加载器加载类(参见getSystemClassLoader()
)。 返回的类对象可能有多个与之相关联的ClassLoader。 ClassLoader的子类通常不需要调用此方法,因为大多数类加载器只需要覆盖findClass(String)
。
name
-
班级的binary name
ClassNotFoundException
- 如果找不到课程
ClassLoader(ClassLoader)
,
getParent()
protected final 类<?> findLoadedClass(String name)
name
-
班级的binary name
protected final void setSigners(类<?> c, Object[] signers)
c
-
类对象
signers
- 该类的签名者
public URL getResource(String name)
资源的名称是标识资源的“ / ”分隔路径名。
此方法首先将搜索父类加载器的资源; 如果父级是null ,则会搜索内置到虚拟机的类加载器的路径。 那个失败,这个方法会调用findResource(String)
来查找资源。
getResources(String)
方法一致。
name
- 资源名称
public Enumeration<URL> getResources(String name) throws IOException
资源的名称是标识资源的/分隔路径名。
搜索顺序在getResource(String)
的文档中描述 。
getResource(String)
方法一致。
这应该确保Enumeration的nextElement
方法返回的第一个元素是与getResource(String)
方法返回的资源相同的资源。
name
- 资源名称
URL
个对象。
如果找不到资源,枚举将为空。
类加载器无权访问的资源将不在枚举中。
IOException
- 如果发生I / O错误
findResources(String)
protected URL findResource(String name)
name
- 资源名称
protected Enumeration<URL> findResources(String name) throws IOException
URL
对象的枚举。
类加载器实现应该覆盖此方法以指定从哪里加载资源。
name
- 资源名称
URL
对象的资源
IOException
- 如果发生I / O错误
protected static boolean registerAsParallelCapable()
请注意,一旦类加载器被注册为并行功能,则无法将其更改。
public static URL getSystemResource(String name)
getSystemClassLoader()
)。
name
- 资源名称
URL
用于读取资源的对象,如果资源无法找到, 则为null
public static Enumeration<URL> getSystemResources(String name) throws IOException
name
- 资源名称
URL
对象
IOException
- 如果发生I / O错误
public InputStream getResourceAsStream(String name)
搜索顺序在getResource(String)
的文档中描述 。
name
- 资源名称
public static InputStream getSystemResourceAsStream(String name)
getSystemClassLoader()
)。
name
- 资源名称
public final ClassLoader getParent()
如果存在安全管理员,并且调用者的类加载器不是null并且不是此类加载器的祖先,则此方法将调用具有RuntimePermission("getClassLoader")
权限的安全管理器的checkPermission
方法来验证是否允许访问父类加载器。 如果没有, SecurityException将被抛出。
SecurityException
- 如果安全管理器存在,并且其
checkPermission方法不允许访问此类加载器的父类加载器。
public static ClassLoader getSystemClassLoader()
该方法首先在运行时的启动顺序中早期被调用,此时它将创建系统类加载器并将其设置为调用Thread的上下文类加载器。
默认的系统类加载器是此类的实现相关实例。
如果在首次调用此方法时定义系统属性“ java.system.class.loader ”,那么该属性的值将被视为将作为系统类加载器返回的类的名称。 类使用默认的系统类加载器加载和必须定义一个公共构造,其被用作代理父ClassLoader类型的单个参数。 然后使用该构造函数创建一个实例,并使用默认的系统类加载器作为参数。 所生成的类加载器被定义为系统类加载器。
如果安全管理器存在,并且调用者的类加载器是不是null和调用者的类加载器是不一样的,或者系统类加载器的祖先,则此方法调用安全管理器的checkPermission
方法与RuntimePermission("getClassLoader")
权限验证访问到系统类加载器。 如果没有, SecurityException将被抛出。
SecurityException
- 如果安全管理器存在,并且其
checkPermission方法不允许访问系统类加载器。
IllegalStateException
- 如果在构建由“
java.system.class.loader ”属性指定的类加载器中递归调用。
Error
- 如果定义了系统属性“ java.system.class.loader ”但是无法加载命名类,则提供程序类不会定义所需的构造函数,或者在构造函数被调用时抛出异常。
错误的根本原因可以通过Throwable.getCause()
方法检索 。
protected 软件包 definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) throws IllegalArgumentException
name
- 包名称
specTitle
- 规格标题
specVersion
- 规格版本
specVendor
- 规格供应商
implTitle
- 实现标题
implVersion
- 实现版本
implVendor
- 实施供应商
sealBase
- 如果不是null ,则该封装相对于给定的代码源URL
对象是密封的。
否则,包装没有密封。
IllegalArgumentException
- 如果程序包名称在该类加载器或其祖先之一中复制现有程序包
protected 软件包 getPackage(String name)
name
- 包名称
protected 软件包[] getPackages()
protected String findLibrary(String libname)
libname
- 图书馆名称
System.loadLibrary(String)
,
System.mapLibraryName(String)
public void setDefaultAssertionStatus(boolean enabled)
setPackageAssertionStatus(String, boolean)
或setClassAssertionStatus(String, boolean)
在每个包或每个类的基础上覆盖此设置。
enabled
-
true如果此类加载器加载的类将在以后默认启用
断言 ,
false如果默认情况下禁用断言。
public void setPackageAssertionStatus(String packageName, boolean enabled)
名为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
- 要设置其包默认断言状态的包的名称。
A null的值表示未命名的包为“current”(参见The Java™ Language Specification的 7.4.2)。
enabled
-
true如果
由此类加载器加载且属于命名的软件包或其任何子软件包的类将默认启用
断言,如果默认情况下禁用断言,则为false。
public void setClassAssertionStatus(String className, boolean enabled)
如果命名类不是顶级类,则此调用对任何类的实际断言状态都不起作用。
className
- 要设置其断言状态的顶级类的完全限定类名。
enabled
-
true如果指定的类要在(及)如果初始化时启用断言,
false如果该类禁用断言。
public void clearAssertionStatus()