JDK API
中的东西:
public abstract class ClassLoader extends Object
class loader
是负责加载类的对象。
ClassLoader
是一个抽象类。给出一个
class
的名字,
class loader
将试图定位或者获得那些构成这个
class
的定义的数据。一个典型的策略是转换该名字为文件名,然后从文件系统中读入该名称的
“class file”
每一个
Class
对象都含有一个指向定义这个
claass
的
ClassLoader
的
reference
数组类的
Class
对象不是由
class loader
创建的,是当需要的时候由
Java runtime
自动产生的。数组类的
class loader
由
Class.getClassLoader()
返回,同它的成员的
classloader
的类型是一样的。如果成员是基本类型,那么该
array class
没有
class loader
。
应用程序需要实现
ClassLoader
的子类以扩展
Java
虚拟机动态加载类的方式。
Class loader
通常由安全管理器使用,用于指示安全域
ClassLoader
使用委托模型来查找
class
和资源。每一个
ClassLoader
的实例都有一个相联系的父
classloader
。当要查找一个
class
或者
resource
时,在自己开始查找之前,
ClassLoader
实例将查询委托给他的父
classloader
。虚拟机建的
class loader
叫做
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();
. . .
网络类加载器子类必须定义方法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
. . .
}
}
构造函数
ClassLoader()、ClassLoader(ClassLoader parent)
方法
a)assert
setDefaultAssertStatus(boolean enabled)
设置确定由此类加载器加载并在将来初始化的类在默认情况下是启用还是禁用断言。
通过调用setPackageAssertionStatus或setClassAssertionStatus在每个包或类上重写此设置
setClassAssetionStatus(String className,boolean enabled)
setPackageAssertionStatus(String packagename, boolean enabled)
clearAssertionStatus(): 默认断言状态设置为false,并放弃与此loader关联的所有默认包或类的断言状态设置
b)define
defineClass() 将一个字节数组转换为Class类的实例
definePackage() 根据name在此ClassLoader中定义包。这允许类加载器定义用于他们的类的包。
包必须在定义类之前创建,包名在类加载器中必须唯一,并且一旦创建就不能重新定义或者更改。
c)find
findClass(String name)在父类加载器检查所请求的类之后,被loadClass调用
findLibrary(String libname)虚拟机调用此方法来查找那些属于利用这个loader加载的类的本机库
findResource()、findResources()查找具有给定名称的资源。类加载器实现应重写此方法。
findLoadedClass(String name)、
findSystemClass(String name) 此方法通过系统加载类来加载该类
d)get
getPackage(String name) getPackages()
返回由此类加载器或其任何祖先所定义的Package
getResource(String name) getResources(String name)
getResourceAsStream(String name)
资源可以是通过类代码与代码位置无关的方式访问的一些数据(图像、声音、文本等)
资源名称是以”/”分隔的标识资源的路径名称
此方法首先搜索资源的父类加载器,如果父类加载器为null,则搜索路径就是虚拟机的内置类加载器的路径
如搜索失败,则此方法调用findResource(String)来查找资源
getSystemResource(String name) getSystemResources(String name)
getSystemResourceAsStream(String name)
getSystemClassLoader()
getParent()
e)load
loadClass(String name) loadClass(String name, boolean resolve)
1.调用findLoadedClass(String)
2. 调用父类加载器的loadClass方法
3. 调用findClass(String)方法
如果resolve标识为true,调用resolveClass(Class)方法
f)other
resolveClass(Class c)、
setSigners(Class c, Object[] signers) 设置类的签署者,应该在定义类后调用此方法
类加载是通过委托来完成的,如果ClassLoader不能找到类,会请求父代ClassLoader来执行此项任务。
所有的
ClassLoader
的根是系统
ClassLoader
,它会以缺省方式装入类,即:从本地文件系统
java.lang
包里面有个
ClassLoader
类,
ClassLoader
的基本目标是对类的请求提供服务,当
JVM
需要使用类时,它根据名称向
ClassLoader
请求这个类,然后
ClassLoader
返回一个表示这个类的
Class
对象。
通过覆盖对应于这个过程不同阶段的方法,可以创建定制的
ClassLoader
。其中的
loadClass(String name,boolean resolve)
方法,该方法为
ClassLoader
的入口点。
loadClass
方法将缺省调用
findClass
方法,自编写的
ClassLoader
就是为了覆盖这两个方法。
怎样读进字节代码,构成一个类对象的:
ClassLoader
里有个方法,
Class defineClass(String name,byte[] b, int off, int len)
,根据
class
字节码文件
(
如
Hello.class)
读进一个字节数组里,
byte[] b
,并把它转化为
class
对象,这些数据可以来源于文件、网络。
defineClass
这个方法把字节代码分析成运行时数据结构、检验有效性等等。该方法被标记成是最终的,不能被覆盖。
其它的一些方法:
findSystemClass
方法:从本地系统装入文件。在本地文件系统中寻找类文件,如果存在,就使用
defineClass
将原始字节转换成
class
对象,以将该文件转换成类。
一、
工作流程
1)
调用
findLoadedClass(String)
来查看是否存在已经装入的类,如果已经存在,获取原始字节
2)
通过父类
ClassLoader
调用
loadClass
方法,如果父类
ClassLoader
是
null
,那么按缺省方式装入类,即系统
ClassLoader
3)
调用
findClass
(
String
)去查找类并获取类
4)
如果
loadClass
的
resolve
参数的值为
true
,那么调用
resolveClass
解析
Class
对象
5)
如果还没有类,返回
ClassNotFoundException
6)
否则,将类返回给调用程序